From 8dac4ee0f673830cc9f31e6c7971cd6bbf1f049f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 02:14:13 +0000 Subject: [PATCH 01/29] feat(api): manual updates --- .stats.yml | 6 +- README.md | 22 +- src/ServiceContracts/SessionsContract.php | 201 +--------- src/ServiceContracts/SessionsRawContract.php | 108 +----- src/Services/SessionsRawService.php | 348 +----------------- src/Services/SessionsService.php | 308 +--------------- src/Sessions/Action.php | 84 ++--- src/Sessions/ModelConfig.php | 113 +----- src/Sessions/ModelConfig/Provider.php | 14 - src/Sessions/ModelConfig/UnionMember1.php | 93 +++++ src/Sessions/SessionActParams.php | 174 --------- src/Sessions/SessionActParams/Input.php | 26 -- src/Sessions/SessionActParams/Options.php | 113 ------ .../SessionActParams/XStreamResponse.php | 12 - src/Sessions/SessionActResponse.php | 127 ------- src/Sessions/SessionEndResponse.php | 48 --- src/Sessions/SessionExecuteAgentParams.php | 157 -------- .../SessionExecuteAgentParams/AgentConfig.php | 121 ------ .../AgentConfig/Model.php | 23 -- .../AgentConfig/Provider.php | 14 - .../ExecuteOptions.php | 111 ------ .../XStreamResponse.php | 12 - src/Sessions/SessionExecuteAgentResponse.php | 54 --- src/Sessions/SessionExtractParams.php | 156 -------- src/Sessions/SessionExtractParams/Options.php | 100 ----- .../SessionExtractParams/XStreamResponse.php | 12 - src/Sessions/SessionExtractResponse.php | 27 -- .../SessionExtractResponse/Extraction.php | 50 --- src/Sessions/SessionNavigateParams.php | 135 ------- .../SessionNavigateParams/Options.php | 61 --- .../Options/WaitUntil.php | 17 - .../SessionNavigateParams/XStreamResponse.php | 12 - src/Sessions/SessionNavigateResponse.php | 79 ---- src/Sessions/SessionObserveParams.php | 131 ------- src/Sessions/SessionObserveParams/Options.php | 100 ----- .../SessionObserveParams/XStreamResponse.php | 12 - src/Sessions/SessionStartParams.php | 151 ++------ src/Sessions/SessionStartResponse.php | 88 ----- tests/Services/SessionsTest.php | 202 +--------- 39 files changed, 222 insertions(+), 3400 deletions(-) delete mode 100644 src/Sessions/ModelConfig/Provider.php create mode 100644 src/Sessions/ModelConfig/UnionMember1.php delete mode 100644 src/Sessions/SessionActParams.php delete mode 100644 src/Sessions/SessionActParams/Input.php delete mode 100644 src/Sessions/SessionActParams/Options.php delete mode 100644 src/Sessions/SessionActParams/XStreamResponse.php delete mode 100644 src/Sessions/SessionActResponse.php delete mode 100644 src/Sessions/SessionEndResponse.php delete mode 100644 src/Sessions/SessionExecuteAgentParams.php delete mode 100644 src/Sessions/SessionExecuteAgentParams/AgentConfig.php delete mode 100644 src/Sessions/SessionExecuteAgentParams/AgentConfig/Model.php delete mode 100644 src/Sessions/SessionExecuteAgentParams/AgentConfig/Provider.php delete mode 100644 src/Sessions/SessionExecuteAgentParams/ExecuteOptions.php delete mode 100644 src/Sessions/SessionExecuteAgentParams/XStreamResponse.php delete mode 100644 src/Sessions/SessionExecuteAgentResponse.php delete mode 100644 src/Sessions/SessionExtractParams.php delete mode 100644 src/Sessions/SessionExtractParams/Options.php delete mode 100644 src/Sessions/SessionExtractParams/XStreamResponse.php delete mode 100644 src/Sessions/SessionExtractResponse.php delete mode 100644 src/Sessions/SessionExtractResponse/Extraction.php delete mode 100644 src/Sessions/SessionNavigateParams.php delete mode 100644 src/Sessions/SessionNavigateParams/Options.php delete mode 100644 src/Sessions/SessionNavigateParams/Options/WaitUntil.php delete mode 100644 src/Sessions/SessionNavigateParams/XStreamResponse.php delete mode 100644 src/Sessions/SessionNavigateResponse.php delete mode 100644 src/Sessions/SessionObserveParams.php delete mode 100644 src/Sessions/SessionObserveParams/Options.php delete mode 100644 src/Sessions/SessionObserveParams/XStreamResponse.php delete mode 100644 src/Sessions/SessionStartResponse.php diff --git a/.stats.yml b/.stats.yml index 36782ae..f5e93e0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-705638ac8966569986bd9ebb7c9761bf0016909e9f2753e77ceabb12c8049511.yml -openapi_spec_hash: a8fbbcaa38e91c7f97313620b42d8d62 +configured_endpoints: 1 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-516862e7e90968bc55ac44ce7ffe2d5c1f738c11757471c2b9e0e4cff9384f2c.yml +openapi_spec_hash: 19bbe52a6ae0eec7fc3f6698e831ee55 config_hash: a35b56eb05306a0f02e83c11d57f975f diff --git a/README.md b/README.md index e045f4e..5eb55ef 100644 --- a/README.md +++ b/README.md @@ -55,20 +55,17 @@ $client = new Client( modelAPIKey: getenv('MODEL_API_KEY') ?: 'My Model API Key', ); -$response = $client->sessions->act( - '00000000-your-session-id-000000000000', - input: 'click the first link on the page', -); +$response = $client->sessions->start(); -var_dump($response->actions); +var_dump($response); ``` ### Value Objects -It is recommended to use the static `with` constructor `Action::with(arguments: ['string'], ...)` +It is recommended to use the static `with` constructor `Dog::with(name: "Joey")` and named parameters to initialize value objects. -However, builders are also provided `(new Action)->withArguments(['string'])`. +However, builders are also provided `(new Dog)->withName("Joey")`. ### Handling errors @@ -80,10 +77,7 @@ When the library is unable to connect to the API, or if the API returns a non-su use Stagehand\Core\Exceptions\APIConnectionException; try { - $response = $client->sessions->start( - browserbaseAPIKey: 'your Browserbase API key', - browserbaseProjectID: 'your Browserbase Project ID', - ); + $response = $client->sessions->start(); } catch (APIConnectionException $e) { echo "The server could not be reached", PHP_EOL; var_dump($e->getPrevious()); @@ -130,9 +124,7 @@ $client = new Client(maxRetries: 0); // Or, configure per-request: $result = $client->sessions->start( - browserbaseAPIKey: 'your Browserbase API key', - browserbaseProjectID: 'your Browserbase Project ID', - requestOptions: RequestOptions::with(maxRetries: 5), + requestOptions: RequestOptions::with(maxRetries: 5) ); ``` @@ -152,8 +144,6 @@ Note: the `extra*` parameters of the same name overrides the documented paramete use Stagehand\RequestOptions; $response = $client->sessions->start( - browserbaseAPIKey: 'your Browserbase API key', - browserbaseProjectID: 'your Browserbase Project ID', requestOptions: RequestOptions::with( extraQueryParams: ['my_query_parameter' => 'value'], extraBodyParams: ['my_body_parameter' => 'value'], diff --git a/src/ServiceContracts/SessionsContract.php b/src/ServiceContracts/SessionsContract.php index c2f3698..f333136 100644 --- a/src/ServiceContracts/SessionsContract.php +++ b/src/ServiceContracts/SessionsContract.php @@ -6,205 +6,26 @@ use Stagehand\Core\Exceptions\APIException; use Stagehand\RequestOptions; -use Stagehand\Sessions\Action; -use Stagehand\Sessions\SessionActParams\XStreamResponse; -use Stagehand\Sessions\SessionActResponse; -use Stagehand\Sessions\SessionEndResponse; -use Stagehand\Sessions\SessionExecuteAgentParams\AgentConfig\Provider; -use Stagehand\Sessions\SessionExecuteAgentResponse; -use Stagehand\Sessions\SessionExtractResponse\Extraction; -use Stagehand\Sessions\SessionNavigateParams\Options\WaitUntil; -use Stagehand\Sessions\SessionNavigateResponse; -use Stagehand\Sessions\SessionStartResponse; interface SessionsContract { /** * @api * - * @param string $sessionID Path param: The session ID returned by /sessions/start - * @param string|array{ - * arguments: list, - * description: string, - * method: string, - * selector: string, - * backendNodeID?: int, - * }|Action $input Body param: Natural language instruction - * @param string $frameID Body param: Frame ID to act on (optional) - * @param array{ - * model?: array{ - * apiKey?: string, - * baseURL?: string, - * model?: string, - * provider?: 'openai'|'anthropic'|'google'|\Stagehand\Sessions\ModelConfig\Provider, - * }, - * timeout?: int, - * variables?: array, - * } $options Body param: - * @param 'true'|'false'|XStreamResponse $xStreamResponse Header param: Enable Server-Sent Events streaming for real-time logs - * - * @throws APIException - */ - public function act( - string $sessionID, - string|array|Action $input, - ?string $frameID = null, - ?array $options = null, - string|XStreamResponse $xStreamResponse = 'true', - ?RequestOptions $requestOptions = null, - ): SessionActResponse; - - /** - * @api - * - * @param string $sessionID The session ID returned by /sessions/start - * - * @throws APIException - */ - public function end( - string $sessionID, - ?RequestOptions $requestOptions = null - ): SessionEndResponse; - - /** - * @api - * - * @param string $sessionID Path param: The session ID returned by /sessions/start - * @param array{ - * cua?: bool, - * model?: string|array{ - * apiKey?: string, - * baseURL?: string, - * model?: string, - * provider?: 'openai'|'anthropic'|'google'|\Stagehand\Sessions\ModelConfig\Provider, - * }, - * provider?: 'openai'|'anthropic'|'google'|Provider, - * systemPrompt?: string, - * } $agentConfig Body param: - * @param array{ - * instruction: string, highlightCursor?: bool, maxSteps?: int - * } $executeOptions Body param: - * @param string $frameID Body param: - * @param 'true'|'false'|\Stagehand\Sessions\SessionExecuteAgentParams\XStreamResponse $xStreamResponse Header param: Enable Server-Sent Events streaming for real-time logs - * - * @throws APIException - */ - public function executeAgent( - string $sessionID, - array $agentConfig, - array $executeOptions, - ?string $frameID = null, - string|\Stagehand\Sessions\SessionExecuteAgentParams\XStreamResponse $xStreamResponse = 'true', - ?RequestOptions $requestOptions = null, - ): SessionExecuteAgentResponse; - - /** - * @api - * - * @param string $sessionID Path param: The session ID returned by /sessions/start - * @param string $frameID Body param: Frame ID to extract from - * @param string $instruction Body param: Natural language instruction for extraction - * @param array{ - * model?: array{ - * apiKey?: string, - * baseURL?: string, - * model?: string, - * provider?: 'openai'|'anthropic'|'google'|\Stagehand\Sessions\ModelConfig\Provider, - * }, - * selector?: string, - * timeout?: int, - * } $options Body param: - * @param array $schema Body param: JSON Schema for structured output - * @param 'true'|'false'|\Stagehand\Sessions\SessionExtractParams\XStreamResponse $xStreamResponse Header param: Enable Server-Sent Events streaming for real-time logs - * - * @return Extraction|array - * - * @throws APIException - */ - public function extract( - string $sessionID, - ?string $frameID = null, - ?string $instruction = null, - ?array $options = null, - ?array $schema = null, - string|\Stagehand\Sessions\SessionExtractParams\XStreamResponse $xStreamResponse = 'true', - ?RequestOptions $requestOptions = null, - ): Extraction|array; - - /** - * @api - * - * @param string $sessionID Path param: The session ID returned by /sessions/start - * @param string $url Body param: URL to navigate to - * @param string $frameID Body param: - * @param array{ - * waitUntil?: 'load'|'domcontentloaded'|'networkidle'|WaitUntil - * } $options Body param: - * @param 'true'|'false'|\Stagehand\Sessions\SessionNavigateParams\XStreamResponse $xStreamResponse Header param: Enable Server-Sent Events streaming for real-time logs - * - * @throws APIException - */ - public function navigate( - string $sessionID, - string $url, - ?string $frameID = null, - ?array $options = null, - string|\Stagehand\Sessions\SessionNavigateParams\XStreamResponse $xStreamResponse = 'true', - ?RequestOptions $requestOptions = null, - ): SessionNavigateResponse; - - /** - * @api - * - * @param string $sessionID Path param: The session ID returned by /sessions/start - * @param string $frameID Body param: Frame ID to observe - * @param string $instruction Body param: Natural language instruction to filter actions - * @param array{ - * model?: array{ - * apiKey?: string, - * baseURL?: string, - * model?: string, - * provider?: 'openai'|'anthropic'|'google'|\Stagehand\Sessions\ModelConfig\Provider, - * }, - * selector?: string, - * timeout?: int, - * } $options Body param: - * @param 'true'|'false'|\Stagehand\Sessions\SessionObserveParams\XStreamResponse $xStreamResponse Header param: Enable Server-Sent Events streaming for real-time logs - * - * @return list - * - * @throws APIException - */ - public function observe( - string $sessionID, - ?string $frameID = null, - ?string $instruction = null, - ?array $options = null, - string|\Stagehand\Sessions\SessionObserveParams\XStreamResponse $xStreamResponse = 'true', - ?RequestOptions $requestOptions = null, - ): array; - - /** - * @api - * - * @param string $browserbaseAPIKey API key for Browserbase Cloud - * @param string $browserbaseProjectID Project ID for Browserbase - * @param int $domSettleTimeout Timeout in ms to wait for DOM to settle - * @param string $model AI model to use for actions (must be prefixed with provider/) - * @param bool $selfHeal Enable self-healing for failed actions - * @param string $systemPrompt Custom system prompt for AI actions - * @param int $verbose Logging verbosity level + * @param mixed $body Body param: + * @param mixed $xLanguage Header param: Client SDK language + * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK + * @param mixed $xSentAt Header param: ISO timestamp when request was sent + * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE * * @throws APIException */ public function start( - string $browserbaseAPIKey, - string $browserbaseProjectID, - ?int $domSettleTimeout = null, - ?string $model = null, - ?bool $selfHeal = null, - ?string $systemPrompt = null, - int $verbose = 0, + mixed $body = null, + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, ?RequestOptions $requestOptions = null, - ): SessionStartResponse; + ): mixed; } diff --git a/src/ServiceContracts/SessionsRawContract.php b/src/ServiceContracts/SessionsRawContract.php index c26faec..fd03a94 100644 --- a/src/ServiceContracts/SessionsRawContract.php +++ b/src/ServiceContracts/SessionsRawContract.php @@ -7,122 +7,16 @@ use Stagehand\Core\Contracts\BaseResponse; use Stagehand\Core\Exceptions\APIException; use Stagehand\RequestOptions; -use Stagehand\Sessions\Action; -use Stagehand\Sessions\SessionActParams; -use Stagehand\Sessions\SessionActResponse; -use Stagehand\Sessions\SessionEndResponse; -use Stagehand\Sessions\SessionExecuteAgentParams; -use Stagehand\Sessions\SessionExecuteAgentResponse; -use Stagehand\Sessions\SessionExtractParams; -use Stagehand\Sessions\SessionExtractResponse\Extraction; -use Stagehand\Sessions\SessionNavigateParams; -use Stagehand\Sessions\SessionNavigateResponse; -use Stagehand\Sessions\SessionObserveParams; use Stagehand\Sessions\SessionStartParams; -use Stagehand\Sessions\SessionStartResponse; interface SessionsRawContract { - /** - * @api - * - * @param string $sessionID Path param: The session ID returned by /sessions/start - * @param array|SessionActParams $params - * - * @return BaseResponse - * - * @throws APIException - */ - public function act( - string $sessionID, - array|SessionActParams $params, - ?RequestOptions $requestOptions = null, - ): BaseResponse; - - /** - * @api - * - * @param string $sessionID The session ID returned by /sessions/start - * - * @return BaseResponse - * - * @throws APIException - */ - public function end( - string $sessionID, - ?RequestOptions $requestOptions = null - ): BaseResponse; - - /** - * @api - * - * @param string $sessionID Path param: The session ID returned by /sessions/start - * @param array|SessionExecuteAgentParams $params - * - * @return BaseResponse - * - * @throws APIException - */ - public function executeAgent( - string $sessionID, - array|SessionExecuteAgentParams $params, - ?RequestOptions $requestOptions = null, - ): BaseResponse; - - /** - * @api - * - * @param string $sessionID Path param: The session ID returned by /sessions/start - * @param array|SessionExtractParams $params - * - * @return BaseResponse> - * - * @throws APIException - */ - public function extract( - string $sessionID, - array|SessionExtractParams $params, - ?RequestOptions $requestOptions = null, - ): BaseResponse; - - /** - * @api - * - * @param string $sessionID Path param: The session ID returned by /sessions/start - * @param array|SessionNavigateParams $params - * - * @return BaseResponse - * - * @throws APIException - */ - public function navigate( - string $sessionID, - array|SessionNavigateParams $params, - ?RequestOptions $requestOptions = null, - ): BaseResponse; - - /** - * @api - * - * @param string $sessionID Path param: The session ID returned by /sessions/start - * @param array|SessionObserveParams $params - * - * @return BaseResponse> - * - * @throws APIException - */ - public function observe( - string $sessionID, - array|SessionObserveParams $params, - ?RequestOptions $requestOptions = null, - ): BaseResponse; - /** * @api * * @param array|SessionStartParams $params * - * @return BaseResponse + * @return BaseResponse * * @throws APIException */ diff --git a/src/Services/SessionsRawService.php b/src/Services/SessionsRawService.php index 2056585..72184cd 100644 --- a/src/Services/SessionsRawService.php +++ b/src/Services/SessionsRawService.php @@ -6,28 +6,11 @@ use Stagehand\Client; use Stagehand\Core\Contracts\BaseResponse; -use Stagehand\Core\Conversion\ListOf; use Stagehand\Core\Exceptions\APIException; use Stagehand\Core\Util; use Stagehand\RequestOptions; use Stagehand\ServiceContracts\SessionsRawContract; -use Stagehand\Sessions\Action; -use Stagehand\Sessions\SessionActParams; -use Stagehand\Sessions\SessionActParams\XStreamResponse; -use Stagehand\Sessions\SessionActResponse; -use Stagehand\Sessions\SessionEndResponse; -use Stagehand\Sessions\SessionExecuteAgentParams; -use Stagehand\Sessions\SessionExecuteAgentParams\AgentConfig\Provider; -use Stagehand\Sessions\SessionExecuteAgentResponse; -use Stagehand\Sessions\SessionExtractParams; -use Stagehand\Sessions\SessionExtractResponse; -use Stagehand\Sessions\SessionExtractResponse\Extraction; -use Stagehand\Sessions\SessionNavigateParams; -use Stagehand\Sessions\SessionNavigateParams\Options\WaitUntil; -use Stagehand\Sessions\SessionNavigateResponse; -use Stagehand\Sessions\SessionObserveParams; use Stagehand\Sessions\SessionStartParams; -use Stagehand\Sessions\SessionStartResponse; final class SessionsRawService implements SessionsRawContract { @@ -40,321 +23,17 @@ public function __construct(private Client $client) {} /** * @api * - * Performs a browser action based on natural language instruction or - * a specific action object returned by observe(). + * Creates a new browser session with the specified configuration. Returns a session ID used for all subsequent operations. * - * @param string $sessionID Path param: The session ID returned by /sessions/start * @param array{ - * input: string|array{ - * arguments: list, - * description: string, - * method: string, - * selector: string, - * backendNodeID?: int, - * }|Action, - * frameID?: string, - * options?: array{ - * model?: array{ - * apiKey?: string, - * baseURL?: string, - * model?: string, - * provider?: 'openai'|'anthropic'|'google'|\Stagehand\Sessions\ModelConfig\Provider, - * }, - * timeout?: int, - * variables?: array, - * }, - * xStreamResponse?: 'true'|'false'|XStreamResponse, - * }|SessionActParams $params - * - * @return BaseResponse - * - * @throws APIException - */ - public function act( - string $sessionID, - array|SessionActParams $params, - ?RequestOptions $requestOptions = null, - ): BaseResponse { - [$parsed, $options] = SessionActParams::parseRequest( - $params, - $requestOptions, - ); - $header_params = ['xStreamResponse' => 'x-stream-response']; - - // @phpstan-ignore-next-line return.type - return $this->client->request( - method: 'post', - path: ['sessions/%1$s/act', $sessionID], - headers: Util::array_transform_keys( - array_intersect_key($parsed, array_flip(array_keys($header_params))), - $header_params, - ), - body: (object) array_diff_key( - $parsed, - array_flip(array_keys($header_params)) - ), - options: $options, - convert: SessionActResponse::class, - ); - } - - /** - * @api - * - * Closes the browser and cleans up all resources associated with the session. - * - * @param string $sessionID The session ID returned by /sessions/start - * - * @return BaseResponse - * - * @throws APIException - */ - public function end( - string $sessionID, - ?RequestOptions $requestOptions = null - ): BaseResponse { - // @phpstan-ignore-next-line return.type - return $this->client->request( - method: 'post', - path: ['sessions/%1$s/end', $sessionID], - options: $requestOptions, - convert: SessionEndResponse::class, - ); - } - - /** - * @api - * - * Runs an autonomous agent that can perform multiple actions to - * complete a complex task. - * - * @param string $sessionID Path param: The session ID returned by /sessions/start - * @param array{ - * agentConfig: array{ - * cua?: bool, - * model?: string|array{ - * apiKey?: string, - * baseURL?: string, - * model?: string, - * provider?: 'openai'|'anthropic'|'google'|\Stagehand\Sessions\ModelConfig\Provider, - * }, - * provider?: 'openai'|'anthropic'|'google'|Provider, - * systemPrompt?: string, - * }, - * executeOptions: array{ - * instruction: string, highlightCursor?: bool, maxSteps?: int - * }, - * frameID?: string, - * xStreamResponse?: 'true'|'false'|SessionExecuteAgentParams\XStreamResponse, - * }|SessionExecuteAgentParams $params - * - * @return BaseResponse - * - * @throws APIException - */ - public function executeAgent( - string $sessionID, - array|SessionExecuteAgentParams $params, - ?RequestOptions $requestOptions = null, - ): BaseResponse { - [$parsed, $options] = SessionExecuteAgentParams::parseRequest( - $params, - $requestOptions, - ); - $header_params = ['xStreamResponse' => 'x-stream-response']; - - // @phpstan-ignore-next-line return.type - return $this->client->request( - method: 'post', - path: ['sessions/%1$s/agentExecute', $sessionID], - headers: Util::array_transform_keys( - array_intersect_key($parsed, array_flip(array_keys($header_params))), - $header_params, - ), - body: (object) array_diff_key( - $parsed, - array_flip(array_keys($header_params)) - ), - options: $options, - convert: SessionExecuteAgentResponse::class, - ); - } - - /** - * @api - * - * Extracts data from the current page using natural language instructions - * and optional JSON schema for structured output. - * - * @param string $sessionID Path param: The session ID returned by /sessions/start - * @param array{ - * frameID?: string, - * instruction?: string, - * options?: array{ - * model?: array{ - * apiKey?: string, - * baseURL?: string, - * model?: string, - * provider?: 'openai'|'anthropic'|'google'|\Stagehand\Sessions\ModelConfig\Provider, - * }, - * selector?: string, - * timeout?: int, - * }, - * schema?: array, - * xStreamResponse?: 'true'|'false'|SessionExtractParams\XStreamResponse, - * }|SessionExtractParams $params - * - * @return BaseResponse> - * - * @throws APIException - */ - public function extract( - string $sessionID, - array|SessionExtractParams $params, - ?RequestOptions $requestOptions = null, - ): BaseResponse { - [$parsed, $options] = SessionExtractParams::parseRequest( - $params, - $requestOptions, - ); - $header_params = ['xStreamResponse' => 'x-stream-response']; - - // @phpstan-ignore-next-line return.type - return $this->client->request( - method: 'post', - path: ['sessions/%1$s/extract', $sessionID], - headers: Util::array_transform_keys( - array_intersect_key($parsed, array_flip(array_keys($header_params))), - $header_params, - ), - body: (object) array_diff_key( - $parsed, - array_flip(array_keys($header_params)) - ), - options: $options, - convert: SessionExtractResponse::class, - ); - } - - /** - * @api - * - * Navigates the browser to the specified URL and waits for page load. - * - * @param string $sessionID Path param: The session ID returned by /sessions/start - * @param array{ - * url: string, - * frameID?: string, - * options?: array{ - * waitUntil?: 'load'|'domcontentloaded'|'networkidle'|WaitUntil - * }, - * xStreamResponse?: 'true'|'false'|SessionNavigateParams\XStreamResponse, - * }|SessionNavigateParams $params - * - * @return BaseResponse - * - * @throws APIException - */ - public function navigate( - string $sessionID, - array|SessionNavigateParams $params, - ?RequestOptions $requestOptions = null, - ): BaseResponse { - [$parsed, $options] = SessionNavigateParams::parseRequest( - $params, - $requestOptions, - ); - $header_params = ['xStreamResponse' => 'x-stream-response']; - - // @phpstan-ignore-next-line return.type - return $this->client->request( - method: 'post', - path: ['sessions/%1$s/navigate', $sessionID], - headers: Util::array_transform_keys( - array_intersect_key($parsed, array_flip(array_keys($header_params))), - $header_params, - ), - body: (object) array_diff_key( - $parsed, - array_flip(array_keys($header_params)) - ), - options: $options, - convert: SessionNavigateResponse::class, - ); - } - - /** - * @api - * - * Returns a list of candidate actions that can be performed on the page, - * optionally filtered by natural language instruction. - * - * @param string $sessionID Path param: The session ID returned by /sessions/start - * @param array{ - * frameID?: string, - * instruction?: string, - * options?: array{ - * model?: array{ - * apiKey?: string, - * baseURL?: string, - * model?: string, - * provider?: 'openai'|'anthropic'|'google'|\Stagehand\Sessions\ModelConfig\Provider, - * }, - * selector?: string, - * timeout?: int, - * }, - * xStreamResponse?: 'true'|'false'|SessionObserveParams\XStreamResponse, - * }|SessionObserveParams $params - * - * @return BaseResponse> - * - * @throws APIException - */ - public function observe( - string $sessionID, - array|SessionObserveParams $params, - ?RequestOptions $requestOptions = null, - ): BaseResponse { - [$parsed, $options] = SessionObserveParams::parseRequest( - $params, - $requestOptions, - ); - $header_params = ['xStreamResponse' => 'x-stream-response']; - - // @phpstan-ignore-next-line return.type - return $this->client->request( - method: 'post', - path: ['sessions/%1$s/observe', $sessionID], - headers: Util::array_transform_keys( - array_intersect_key($parsed, array_flip(array_keys($header_params))), - $header_params, - ), - body: (object) array_diff_key( - $parsed, - array_flip(array_keys($header_params)) - ), - options: $options, - convert: new ListOf(Action::class), - ); - } - - /** - * @api - * - * Initializes a new Stagehand session with a browser instance. - * Returns a session ID that must be used for all subsequent requests. - * - * @param array{ - * browserbaseAPIKey: string, - * browserbaseProjectID: string, - * domSettleTimeout?: int, - * model?: string, - * selfHeal?: bool, - * systemPrompt?: string, - * verbose?: int, + * body?: mixed, + * xLanguage?: mixed, + * xSDKVersion?: mixed, + * xSentAt?: mixed, + * xStreamResponse?: mixed, * }|SessionStartParams $params * - * @return BaseResponse + * @return BaseResponse * * @throws APIException */ @@ -371,9 +50,18 @@ public function start( return $this->client->request( method: 'post', path: 'sessions/start', - body: (object) $parsed, + headers: Util::array_transform_keys( + array_diff_key($parsed, array_flip(['body'])), + [ + 'xLanguage' => 'x-language', + 'xSDKVersion' => 'x-sdk-version', + 'xSentAt' => 'x-sent-at', + 'xStreamResponse' => 'x-stream-response', + ], + ), + body: $parsed['body'], options: $options, - convert: SessionStartResponse::class, + convert: 'mixed', ); } } diff --git a/src/Services/SessionsService.php b/src/Services/SessionsService.php index ed6dfc0..0ae7461 100644 --- a/src/Services/SessionsService.php +++ b/src/Services/SessionsService.php @@ -9,16 +9,6 @@ use Stagehand\Core\Util; use Stagehand\RequestOptions; use Stagehand\ServiceContracts\SessionsContract; -use Stagehand\Sessions\Action; -use Stagehand\Sessions\SessionActParams\XStreamResponse; -use Stagehand\Sessions\SessionActResponse; -use Stagehand\Sessions\SessionEndResponse; -use Stagehand\Sessions\SessionExecuteAgentParams\AgentConfig\Provider; -use Stagehand\Sessions\SessionExecuteAgentResponse; -use Stagehand\Sessions\SessionExtractResponse\Extraction; -use Stagehand\Sessions\SessionNavigateParams\Options\WaitUntil; -use Stagehand\Sessions\SessionNavigateResponse; -use Stagehand\Sessions\SessionStartResponse; final class SessionsService implements SessionsContract { @@ -38,295 +28,31 @@ public function __construct(private Client $client) /** * @api * - * Performs a browser action based on natural language instruction or - * a specific action object returned by observe(). + * Creates a new browser session with the specified configuration. Returns a session ID used for all subsequent operations. * - * @param string $sessionID Path param: The session ID returned by /sessions/start - * @param string|array{ - * arguments: list, - * description: string, - * method: string, - * selector: string, - * backendNodeID?: int, - * }|Action $input Body param: Natural language instruction - * @param string $frameID Body param: Frame ID to act on (optional) - * @param array{ - * model?: array{ - * apiKey?: string, - * baseURL?: string, - * model?: string, - * provider?: 'openai'|'anthropic'|'google'|\Stagehand\Sessions\ModelConfig\Provider, - * }, - * timeout?: int, - * variables?: array, - * } $options Body param: - * @param 'true'|'false'|XStreamResponse $xStreamResponse Header param: Enable Server-Sent Events streaming for real-time logs - * - * @throws APIException - */ - public function act( - string $sessionID, - string|array|Action $input, - ?string $frameID = null, - ?array $options = null, - string|XStreamResponse $xStreamResponse = 'true', - ?RequestOptions $requestOptions = null, - ): SessionActResponse { - $params = Util::removeNulls( - [ - 'input' => $input, - 'frameID' => $frameID, - 'options' => $options, - 'xStreamResponse' => $xStreamResponse, - ], - ); - - // @phpstan-ignore-next-line argument.type - $response = $this->raw->act($sessionID, params: $params, requestOptions: $requestOptions); - - return $response->parse(); - } - - /** - * @api - * - * Closes the browser and cleans up all resources associated with the session. - * - * @param string $sessionID The session ID returned by /sessions/start - * - * @throws APIException - */ - public function end( - string $sessionID, - ?RequestOptions $requestOptions = null - ): SessionEndResponse { - // @phpstan-ignore-next-line argument.type - $response = $this->raw->end($sessionID, requestOptions: $requestOptions); - - return $response->parse(); - } - - /** - * @api - * - * Runs an autonomous agent that can perform multiple actions to - * complete a complex task. - * - * @param string $sessionID Path param: The session ID returned by /sessions/start - * @param array{ - * cua?: bool, - * model?: string|array{ - * apiKey?: string, - * baseURL?: string, - * model?: string, - * provider?: 'openai'|'anthropic'|'google'|\Stagehand\Sessions\ModelConfig\Provider, - * }, - * provider?: 'openai'|'anthropic'|'google'|Provider, - * systemPrompt?: string, - * } $agentConfig Body param: - * @param array{ - * instruction: string, highlightCursor?: bool, maxSteps?: int - * } $executeOptions Body param: - * @param string $frameID Body param: - * @param 'true'|'false'|\Stagehand\Sessions\SessionExecuteAgentParams\XStreamResponse $xStreamResponse Header param: Enable Server-Sent Events streaming for real-time logs - * - * @throws APIException - */ - public function executeAgent( - string $sessionID, - array $agentConfig, - array $executeOptions, - ?string $frameID = null, - string|\Stagehand\Sessions\SessionExecuteAgentParams\XStreamResponse $xStreamResponse = 'true', - ?RequestOptions $requestOptions = null, - ): SessionExecuteAgentResponse { - $params = Util::removeNulls( - [ - 'agentConfig' => $agentConfig, - 'executeOptions' => $executeOptions, - 'frameID' => $frameID, - 'xStreamResponse' => $xStreamResponse, - ], - ); - - // @phpstan-ignore-next-line argument.type - $response = $this->raw->executeAgent($sessionID, params: $params, requestOptions: $requestOptions); - - return $response->parse(); - } - - /** - * @api - * - * Extracts data from the current page using natural language instructions - * and optional JSON schema for structured output. - * - * @param string $sessionID Path param: The session ID returned by /sessions/start - * @param string $frameID Body param: Frame ID to extract from - * @param string $instruction Body param: Natural language instruction for extraction - * @param array{ - * model?: array{ - * apiKey?: string, - * baseURL?: string, - * model?: string, - * provider?: 'openai'|'anthropic'|'google'|\Stagehand\Sessions\ModelConfig\Provider, - * }, - * selector?: string, - * timeout?: int, - * } $options Body param: - * @param array $schema Body param: JSON Schema for structured output - * @param 'true'|'false'|\Stagehand\Sessions\SessionExtractParams\XStreamResponse $xStreamResponse Header param: Enable Server-Sent Events streaming for real-time logs - * - * @return Extraction|array - * - * @throws APIException - */ - public function extract( - string $sessionID, - ?string $frameID = null, - ?string $instruction = null, - ?array $options = null, - ?array $schema = null, - string|\Stagehand\Sessions\SessionExtractParams\XStreamResponse $xStreamResponse = 'true', - ?RequestOptions $requestOptions = null, - ): Extraction|array { - $params = Util::removeNulls( - [ - 'frameID' => $frameID, - 'instruction' => $instruction, - 'options' => $options, - 'schema' => $schema, - 'xStreamResponse' => $xStreamResponse, - ], - ); - - // @phpstan-ignore-next-line argument.type - $response = $this->raw->extract($sessionID, params: $params, requestOptions: $requestOptions); - - return $response->parse(); - } - - /** - * @api - * - * Navigates the browser to the specified URL and waits for page load. - * - * @param string $sessionID Path param: The session ID returned by /sessions/start - * @param string $url Body param: URL to navigate to - * @param string $frameID Body param: - * @param array{ - * waitUntil?: 'load'|'domcontentloaded'|'networkidle'|WaitUntil - * } $options Body param: - * @param 'true'|'false'|\Stagehand\Sessions\SessionNavigateParams\XStreamResponse $xStreamResponse Header param: Enable Server-Sent Events streaming for real-time logs - * - * @throws APIException - */ - public function navigate( - string $sessionID, - string $url, - ?string $frameID = null, - ?array $options = null, - string|\Stagehand\Sessions\SessionNavigateParams\XStreamResponse $xStreamResponse = 'true', - ?RequestOptions $requestOptions = null, - ): SessionNavigateResponse { - $params = Util::removeNulls( - [ - 'url' => $url, - 'frameID' => $frameID, - 'options' => $options, - 'xStreamResponse' => $xStreamResponse, - ], - ); - - // @phpstan-ignore-next-line argument.type - $response = $this->raw->navigate($sessionID, params: $params, requestOptions: $requestOptions); - - return $response->parse(); - } - - /** - * @api - * - * Returns a list of candidate actions that can be performed on the page, - * optionally filtered by natural language instruction. - * - * @param string $sessionID Path param: The session ID returned by /sessions/start - * @param string $frameID Body param: Frame ID to observe - * @param string $instruction Body param: Natural language instruction to filter actions - * @param array{ - * model?: array{ - * apiKey?: string, - * baseURL?: string, - * model?: string, - * provider?: 'openai'|'anthropic'|'google'|\Stagehand\Sessions\ModelConfig\Provider, - * }, - * selector?: string, - * timeout?: int, - * } $options Body param: - * @param 'true'|'false'|\Stagehand\Sessions\SessionObserveParams\XStreamResponse $xStreamResponse Header param: Enable Server-Sent Events streaming for real-time logs - * - * @return list - * - * @throws APIException - */ - public function observe( - string $sessionID, - ?string $frameID = null, - ?string $instruction = null, - ?array $options = null, - string|\Stagehand\Sessions\SessionObserveParams\XStreamResponse $xStreamResponse = 'true', - ?RequestOptions $requestOptions = null, - ): array { - $params = Util::removeNulls( - [ - 'frameID' => $frameID, - 'instruction' => $instruction, - 'options' => $options, - 'xStreamResponse' => $xStreamResponse, - ], - ); - - // @phpstan-ignore-next-line argument.type - $response = $this->raw->observe($sessionID, params: $params, requestOptions: $requestOptions); - - return $response->parse(); - } - - /** - * @api - * - * Initializes a new Stagehand session with a browser instance. - * Returns a session ID that must be used for all subsequent requests. - * - * @param string $browserbaseAPIKey API key for Browserbase Cloud - * @param string $browserbaseProjectID Project ID for Browserbase - * @param int $domSettleTimeout Timeout in ms to wait for DOM to settle - * @param string $model AI model to use for actions (must be prefixed with provider/) - * @param bool $selfHeal Enable self-healing for failed actions - * @param string $systemPrompt Custom system prompt for AI actions - * @param int $verbose Logging verbosity level + * @param mixed $body Body param: + * @param mixed $xLanguage Header param: Client SDK language + * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK + * @param mixed $xSentAt Header param: ISO timestamp when request was sent + * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE * * @throws APIException */ public function start( - string $browserbaseAPIKey, - string $browserbaseProjectID, - ?int $domSettleTimeout = null, - ?string $model = null, - ?bool $selfHeal = null, - ?string $systemPrompt = null, - int $verbose = 0, + mixed $body = null, + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, ?RequestOptions $requestOptions = null, - ): SessionStartResponse { + ): mixed { $params = Util::removeNulls( [ - 'browserbaseAPIKey' => $browserbaseAPIKey, - 'browserbaseProjectID' => $browserbaseProjectID, - 'domSettleTimeout' => $domSettleTimeout, - 'model' => $model, - 'selfHeal' => $selfHeal, - 'systemPrompt' => $systemPrompt, - 'verbose' => $verbose, + 'body' => $body, + 'xLanguage' => $xLanguage, + 'xSDKVersion' => $xSDKVersion, + 'xSentAt' => $xSentAt, + 'xStreamResponse' => $xStreamResponse, ], ); diff --git a/src/Sessions/Action.php b/src/Sessions/Action.php index acd24fb..6ddbf07 100644 --- a/src/Sessions/Action.php +++ b/src/Sessions/Action.php @@ -10,12 +10,13 @@ use Stagehand\Core\Contracts\BaseModel; /** + * Action object returned by observe and used by act. + * * @phpstan-type ActionShape = array{ - * arguments: list, * description: string, - * method: string, * selector: string, - * backendNodeID?: int|null, + * arguments?: list|null, + * method?: string|null, * } */ final class Action implements BaseModel @@ -23,14 +24,6 @@ final class Action implements BaseModel /** @use SdkModel */ use SdkModel; - /** - * Arguments for the method. - * - * @var list $arguments - */ - #[Required(list: 'string')] - public array $arguments; - /** * Human-readable description of the action. */ @@ -38,39 +31,37 @@ final class Action implements BaseModel public string $description; /** - * Method to execute (e.g., "click", "fill"). + * CSS selector or XPath for the element. */ #[Required] - public string $method; + public string $selector; /** - * CSS or XPath selector for the element. + * Arguments to pass to the method. + * + * @var list|null $arguments */ - #[Required] - public string $selector; + #[Optional(list: 'string')] + public ?array $arguments; /** - * CDP backend node ID. + * The method to execute (click, fill, etc.). */ - #[Optional('backendNodeId')] - public ?int $backendNodeID; + #[Optional] + public ?string $method; /** * `new Action()` is missing required properties by the API. * * To enforce required parameters use * ``` - * Action::with(arguments: ..., description: ..., method: ..., selector: ...) + * Action::with(description: ..., selector: ...) * ``` * * Otherwise ensure the following setters are called * * ``` - * (new Action) - * ->withArguments(...) - * ->withDescription(...) - * ->withMethod(...) - * ->withSelector(...) + * (new Action)->withDescription(...)->withSelector(...) * ``` */ public function __construct() @@ -86,33 +77,18 @@ public function __construct() * @param list $arguments */ public static function with( - array $arguments, string $description, - string $method, string $selector, - ?int $backendNodeID = null, + ?array $arguments = null, + ?string $method = null, ): self { $self = new self; - $self['arguments'] = $arguments; $self['description'] = $description; - $self['method'] = $method; $self['selector'] = $selector; - null !== $backendNodeID && $self['backendNodeID'] = $backendNodeID; - - return $self; - } - - /** - * Arguments for the method. - * - * @param list $arguments - */ - public function withArguments(array $arguments): self - { - $self = clone $this; - $self['arguments'] = $arguments; + null !== $arguments && $self['arguments'] = $arguments; + null !== $method && $self['method'] = $method; return $self; } @@ -129,34 +105,36 @@ public function withDescription(string $description): self } /** - * Method to execute (e.g., "click", "fill"). + * CSS selector or XPath for the element. */ - public function withMethod(string $method): self + public function withSelector(string $selector): self { $self = clone $this; - $self['method'] = $method; + $self['selector'] = $selector; return $self; } /** - * CSS or XPath selector for the element. + * Arguments to pass to the method. + * + * @param list $arguments */ - public function withSelector(string $selector): self + public function withArguments(array $arguments): self { $self = clone $this; - $self['selector'] = $selector; + $self['arguments'] = $arguments; return $self; } /** - * CDP backend node ID. + * The method to execute (click, fill, etc.). */ - public function withBackendNodeID(int $backendNodeID): self + public function withMethod(string $method): self { $self = clone $this; - $self['backendNodeID'] = $backendNodeID; + $self['method'] = $method; return $self; } diff --git a/src/Sessions/ModelConfig.php b/src/Sessions/ModelConfig.php index 3f5a2e8..47c97ad 100644 --- a/src/Sessions/ModelConfig.php +++ b/src/Sessions/ModelConfig.php @@ -4,115 +4,20 @@ namespace Stagehand\Sessions; -use Stagehand\Core\Attributes\Optional; -use Stagehand\Core\Concerns\SdkModel; -use Stagehand\Core\Contracts\BaseModel; -use Stagehand\Sessions\ModelConfig\Provider; +use Stagehand\Core\Concerns\SdkUnion; +use Stagehand\Core\Conversion\Contracts\Converter; +use Stagehand\Core\Conversion\Contracts\ConverterSource; +use Stagehand\Sessions\ModelConfig\UnionMember1; -/** - * @phpstan-type ModelConfigShape = array{ - * apiKey?: string|null, - * baseURL?: string|null, - * model?: string|null, - * provider?: value-of|null, - * } - */ -final class ModelConfig implements BaseModel +final class ModelConfig implements ConverterSource { - /** @use SdkModel */ - use SdkModel; + use SdkUnion; /** - * API key for the model provider. + * @return list|array */ - #[Optional] - public ?string $apiKey; - - /** - * Custom base URL for API. - */ - #[Optional] - public ?string $baseURL; - - /** - * Model name. - */ - #[Optional] - public ?string $model; - - /** @var value-of|null $provider */ - #[Optional(enum: Provider::class)] - public ?string $provider; - - public function __construct() - { - $this->initialize(); - } - - /** - * Construct an instance from the required parameters. - * - * You must use named parameters to construct any parameters with a default value. - * - * @param Provider|value-of $provider - */ - public static function with( - ?string $apiKey = null, - ?string $baseURL = null, - ?string $model = null, - Provider|string|null $provider = null, - ): self { - $self = new self; - - null !== $apiKey && $self['apiKey'] = $apiKey; - null !== $baseURL && $self['baseURL'] = $baseURL; - null !== $model && $self['model'] = $model; - null !== $provider && $self['provider'] = $provider; - - return $self; - } - - /** - * API key for the model provider. - */ - public function withAPIKey(string $apiKey): self + public static function variants(): array { - $self = clone $this; - $self['apiKey'] = $apiKey; - - return $self; - } - - /** - * Custom base URL for API. - */ - public function withBaseURL(string $baseURL): self - { - $self = clone $this; - $self['baseURL'] = $baseURL; - - return $self; - } - - /** - * Model name. - */ - public function withModel(string $model): self - { - $self = clone $this; - $self['model'] = $model; - - return $self; - } - - /** - * @param Provider|value-of $provider - */ - public function withProvider(Provider|string $provider): self - { - $self = clone $this; - $self['provider'] = $provider; - - return $self; + return ['string', UnionMember1::class]; } } diff --git a/src/Sessions/ModelConfig/Provider.php b/src/Sessions/ModelConfig/Provider.php deleted file mode 100644 index a0e717e..0000000 --- a/src/Sessions/ModelConfig/Provider.php +++ /dev/null @@ -1,14 +0,0 @@ - */ + use SdkModel; + + #[Required] + public string $modelName; + + #[Optional] + public ?string $apiKey; + + #[Optional] + public ?string $baseURL; + + /** + * `new UnionMember1()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * UnionMember1::with(modelName: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new UnionMember1)->withModelName(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with( + string $modelName, + ?string $apiKey = null, + ?string $baseURL = null + ): self { + $self = new self; + + $self['modelName'] = $modelName; + + null !== $apiKey && $self['apiKey'] = $apiKey; + null !== $baseURL && $self['baseURL'] = $baseURL; + + return $self; + } + + public function withModelName(string $modelName): self + { + $self = clone $this; + $self['modelName'] = $modelName; + + return $self; + } + + public function withAPIKey(string $apiKey): self + { + $self = clone $this; + $self['apiKey'] = $apiKey; + + return $self; + } + + public function withBaseURL(string $baseURL): self + { + $self = clone $this; + $self['baseURL'] = $baseURL; + + return $self; + } +} diff --git a/src/Sessions/SessionActParams.php b/src/Sessions/SessionActParams.php deleted file mode 100644 index 08fa0d7..0000000 --- a/src/Sessions/SessionActParams.php +++ /dev/null @@ -1,174 +0,0 @@ -, - * description: string, - * method: string, - * selector: string, - * backendNodeID?: int|null, - * }, - * frameID?: string, - * options?: Options|array{ - * model?: ModelConfig|null, - * timeout?: int|null, - * variables?: array|null, - * }, - * xStreamResponse?: XStreamResponse|value-of, - * } - */ -final class SessionActParams implements BaseModel -{ - /** @use SdkModel */ - use SdkModel; - use SdkParams; - - /** - * Natural language instruction. - */ - #[Required] - public string|Action $input; - - /** - * Frame ID to act on (optional). - */ - #[Optional('frameId')] - public ?string $frameID; - - #[Optional] - public ?Options $options; - - /** @var value-of|null $xStreamResponse */ - #[Optional(enum: XStreamResponse::class)] - public ?string $xStreamResponse; - - /** - * `new SessionActParams()` is missing required properties by the API. - * - * To enforce required parameters use - * ``` - * SessionActParams::with(input: ...) - * ``` - * - * Otherwise ensure the following setters are called - * - * ``` - * (new SessionActParams)->withInput(...) - * ``` - */ - public function __construct() - { - $this->initialize(); - } - - /** - * Construct an instance from the required parameters. - * - * You must use named parameters to construct any parameters with a default value. - * - * @param string|Action|array{ - * arguments: list, - * description: string, - * method: string, - * selector: string, - * backendNodeID?: int|null, - * } $input - * @param Options|array{ - * model?: ModelConfig|null, - * timeout?: int|null, - * variables?: array|null, - * } $options - * @param XStreamResponse|value-of $xStreamResponse - */ - public static function with( - string|Action|array $input, - ?string $frameID = null, - Options|array|null $options = null, - XStreamResponse|string|null $xStreamResponse = null, - ): self { - $self = new self; - - $self['input'] = $input; - - null !== $frameID && $self['frameID'] = $frameID; - null !== $options && $self['options'] = $options; - null !== $xStreamResponse && $self['xStreamResponse'] = $xStreamResponse; - - return $self; - } - - /** - * Natural language instruction. - * - * @param string|Action|array{ - * arguments: list, - * description: string, - * method: string, - * selector: string, - * backendNodeID?: int|null, - * } $input - */ - public function withInput(string|Action|array $input): self - { - $self = clone $this; - $self['input'] = $input; - - return $self; - } - - /** - * Frame ID to act on (optional). - */ - public function withFrameID(string $frameID): self - { - $self = clone $this; - $self['frameID'] = $frameID; - - return $self; - } - - /** - * @param Options|array{ - * model?: ModelConfig|null, - * timeout?: int|null, - * variables?: array|null, - * } $options - */ - public function withOptions(Options|array $options): self - { - $self = clone $this; - $self['options'] = $options; - - return $self; - } - - /** - * @param XStreamResponse|value-of $xStreamResponse - */ - public function withXStreamResponse( - XStreamResponse|string $xStreamResponse - ): self { - $self = clone $this; - $self['xStreamResponse'] = $xStreamResponse; - - return $self; - } -} diff --git a/src/Sessions/SessionActParams/Input.php b/src/Sessions/SessionActParams/Input.php deleted file mode 100644 index fe1645f..0000000 --- a/src/Sessions/SessionActParams/Input.php +++ /dev/null @@ -1,26 +0,0 @@ -|array - */ - public static function variants(): array - { - return ['string', Action::class]; - } -} diff --git a/src/Sessions/SessionActParams/Options.php b/src/Sessions/SessionActParams/Options.php deleted file mode 100644 index 37a97d6..0000000 --- a/src/Sessions/SessionActParams/Options.php +++ /dev/null @@ -1,113 +0,0 @@ -|null, - * } - */ -final class Options implements BaseModel -{ - /** @use SdkModel */ - use SdkModel; - - #[Optional] - public ?ModelConfig $model; - - /** - * Timeout in milliseconds. - */ - #[Optional] - public ?int $timeout; - - /** - * Template variables for instruction. - * - * @var array|null $variables - */ - #[Optional(map: 'string')] - public ?array $variables; - - public function __construct() - { - $this->initialize(); - } - - /** - * Construct an instance from the required parameters. - * - * You must use named parameters to construct any parameters with a default value. - * - * @param ModelConfig|array{ - * apiKey?: string|null, - * baseURL?: string|null, - * model?: string|null, - * provider?: value-of|null, - * } $model - * @param array $variables - */ - public static function with( - ModelConfig|array|null $model = null, - ?int $timeout = null, - ?array $variables = null, - ): self { - $self = new self; - - null !== $model && $self['model'] = $model; - null !== $timeout && $self['timeout'] = $timeout; - null !== $variables && $self['variables'] = $variables; - - return $self; - } - - /** - * @param ModelConfig|array{ - * apiKey?: string|null, - * baseURL?: string|null, - * model?: string|null, - * provider?: value-of|null, - * } $model - */ - public function withModel(ModelConfig|array $model): self - { - $self = clone $this; - $self['model'] = $model; - - return $self; - } - - /** - * Timeout in milliseconds. - */ - public function withTimeout(int $timeout): self - { - $self = clone $this; - $self['timeout'] = $timeout; - - return $self; - } - - /** - * Template variables for instruction. - * - * @param array $variables - */ - public function withVariables(array $variables): self - { - $self = clone $this; - $self['variables'] = $variables; - - return $self; - } -} diff --git a/src/Sessions/SessionActParams/XStreamResponse.php b/src/Sessions/SessionActParams/XStreamResponse.php deleted file mode 100644 index 7ce15be..0000000 --- a/src/Sessions/SessionActParams/XStreamResponse.php +++ /dev/null @@ -1,12 +0,0 @@ -, message: string, success: bool - * } - */ -final class SessionActResponse implements BaseModel -{ - /** @use SdkModel */ - use SdkModel; - - /** - * Actions that were executed. - * - * @var list $actions - */ - #[Required(list: Action::class)] - public array $actions; - - /** - * Result message. - */ - #[Required] - public string $message; - - /** - * Whether the action succeeded. - */ - #[Required] - public bool $success; - - /** - * `new SessionActResponse()` is missing required properties by the API. - * - * To enforce required parameters use - * ``` - * SessionActResponse::with(actions: ..., message: ..., success: ...) - * ``` - * - * Otherwise ensure the following setters are called - * - * ``` - * (new SessionActResponse)->withActions(...)->withMessage(...)->withSuccess(...) - * ``` - */ - public function __construct() - { - $this->initialize(); - } - - /** - * Construct an instance from the required parameters. - * - * You must use named parameters to construct any parameters with a default value. - * - * @param list, - * description: string, - * method: string, - * selector: string, - * backendNodeID?: int|null, - * }> $actions - */ - public static function with( - array $actions, - string $message, - bool $success - ): self { - $self = new self; - - $self['actions'] = $actions; - $self['message'] = $message; - $self['success'] = $success; - - return $self; - } - - /** - * Actions that were executed. - * - * @param list, - * description: string, - * method: string, - * selector: string, - * backendNodeID?: int|null, - * }> $actions - */ - public function withActions(array $actions): self - { - $self = clone $this; - $self['actions'] = $actions; - - return $self; - } - - /** - * Result message. - */ - public function withMessage(string $message): self - { - $self = clone $this; - $self['message'] = $message; - - return $self; - } - - /** - * Whether the action succeeded. - */ - public function withSuccess(bool $success): self - { - $self = clone $this; - $self['success'] = $success; - - return $self; - } -} diff --git a/src/Sessions/SessionEndResponse.php b/src/Sessions/SessionEndResponse.php deleted file mode 100644 index 17788a0..0000000 --- a/src/Sessions/SessionEndResponse.php +++ /dev/null @@ -1,48 +0,0 @@ - */ - use SdkModel; - - #[Optional] - public ?bool $success; - - public function __construct() - { - $this->initialize(); - } - - /** - * Construct an instance from the required parameters. - * - * You must use named parameters to construct any parameters with a default value. - */ - public static function with(?bool $success = null): self - { - $self = new self; - - null !== $success && $self['success'] = $success; - - return $self; - } - - public function withSuccess(bool $success): self - { - $self = clone $this; - $self['success'] = $success; - - return $self; - } -} diff --git a/src/Sessions/SessionExecuteAgentParams.php b/src/Sessions/SessionExecuteAgentParams.php deleted file mode 100644 index fc541ff..0000000 --- a/src/Sessions/SessionExecuteAgentParams.php +++ /dev/null @@ -1,157 +0,0 @@ -|null, - * systemPrompt?: string|null, - * }, - * executeOptions: ExecuteOptions|array{ - * instruction: string, highlightCursor?: bool|null, maxSteps?: int|null - * }, - * frameID?: string, - * xStreamResponse?: XStreamResponse|value-of, - * } - */ -final class SessionExecuteAgentParams implements BaseModel -{ - /** @use SdkModel */ - use SdkModel; - use SdkParams; - - #[Required] - public AgentConfig $agentConfig; - - #[Required] - public ExecuteOptions $executeOptions; - - #[Optional('frameId')] - public ?string $frameID; - - /** @var value-of|null $xStreamResponse */ - #[Optional(enum: XStreamResponse::class)] - public ?string $xStreamResponse; - - /** - * `new SessionExecuteAgentParams()` is missing required properties by the API. - * - * To enforce required parameters use - * ``` - * SessionExecuteAgentParams::with(agentConfig: ..., executeOptions: ...) - * ``` - * - * Otherwise ensure the following setters are called - * - * ``` - * (new SessionExecuteAgentParams)->withAgentConfig(...)->withExecuteOptions(...) - * ``` - */ - public function __construct() - { - $this->initialize(); - } - - /** - * Construct an instance from the required parameters. - * - * You must use named parameters to construct any parameters with a default value. - * - * @param AgentConfig|array{ - * cua?: bool|null, - * model?: string|ModelConfig|null, - * provider?: value-of|null, - * systemPrompt?: string|null, - * } $agentConfig - * @param ExecuteOptions|array{ - * instruction: string, highlightCursor?: bool|null, maxSteps?: int|null - * } $executeOptions - * @param XStreamResponse|value-of $xStreamResponse - */ - public static function with( - AgentConfig|array $agentConfig, - ExecuteOptions|array $executeOptions, - ?string $frameID = null, - XStreamResponse|string|null $xStreamResponse = null, - ): self { - $self = new self; - - $self['agentConfig'] = $agentConfig; - $self['executeOptions'] = $executeOptions; - - null !== $frameID && $self['frameID'] = $frameID; - null !== $xStreamResponse && $self['xStreamResponse'] = $xStreamResponse; - - return $self; - } - - /** - * @param AgentConfig|array{ - * cua?: bool|null, - * model?: string|ModelConfig|null, - * provider?: value-of|null, - * systemPrompt?: string|null, - * } $agentConfig - */ - public function withAgentConfig(AgentConfig|array $agentConfig): self - { - $self = clone $this; - $self['agentConfig'] = $agentConfig; - - return $self; - } - - /** - * @param ExecuteOptions|array{ - * instruction: string, highlightCursor?: bool|null, maxSteps?: int|null - * } $executeOptions - */ - public function withExecuteOptions( - ExecuteOptions|array $executeOptions - ): self { - $self = clone $this; - $self['executeOptions'] = $executeOptions; - - return $self; - } - - public function withFrameID(string $frameID): self - { - $self = clone $this; - $self['frameID'] = $frameID; - - return $self; - } - - /** - * @param XStreamResponse|value-of $xStreamResponse - */ - public function withXStreamResponse( - XStreamResponse|string $xStreamResponse - ): self { - $self = clone $this; - $self['xStreamResponse'] = $xStreamResponse; - - return $self; - } -} diff --git a/src/Sessions/SessionExecuteAgentParams/AgentConfig.php b/src/Sessions/SessionExecuteAgentParams/AgentConfig.php deleted file mode 100644 index d052c16..0000000 --- a/src/Sessions/SessionExecuteAgentParams/AgentConfig.php +++ /dev/null @@ -1,121 +0,0 @@ -|null, - * systemPrompt?: string|null, - * } - */ -final class AgentConfig implements BaseModel -{ - /** @use SdkModel */ - use SdkModel; - - /** - * Enable Computer Use Agent mode. - */ - #[Optional] - public ?bool $cua; - - #[Optional] - public string|ModelConfig|null $model; - - /** @var value-of|null $provider */ - #[Optional(enum: Provider::class)] - public ?string $provider; - - #[Optional] - public ?string $systemPrompt; - - public function __construct() - { - $this->initialize(); - } - - /** - * Construct an instance from the required parameters. - * - * You must use named parameters to construct any parameters with a default value. - * - * @param string|ModelConfig|array{ - * apiKey?: string|null, - * baseURL?: string|null, - * model?: string|null, - * provider?: value-of|null, - * } $model - * @param Provider|value-of $provider - */ - public static function with( - ?bool $cua = null, - string|ModelConfig|array|null $model = null, - Provider|string|null $provider = null, - ?string $systemPrompt = null, - ): self { - $self = new self; - - null !== $cua && $self['cua'] = $cua; - null !== $model && $self['model'] = $model; - null !== $provider && $self['provider'] = $provider; - null !== $systemPrompt && $self['systemPrompt'] = $systemPrompt; - - return $self; - } - - /** - * Enable Computer Use Agent mode. - */ - public function withCua(bool $cua): self - { - $self = clone $this; - $self['cua'] = $cua; - - return $self; - } - - /** - * @param string|ModelConfig|array{ - * apiKey?: string|null, - * baseURL?: string|null, - * model?: string|null, - * provider?: value-of|null, - * } $model - */ - public function withModel(string|ModelConfig|array $model): self - { - $self = clone $this; - $self['model'] = $model; - - return $self; - } - - /** - * @param Provider|value-of $provider - */ - public function withProvider(Provider|string $provider): self - { - $self = clone $this; - $self['provider'] = $provider; - - return $self; - } - - public function withSystemPrompt(string $systemPrompt): self - { - $self = clone $this; - $self['systemPrompt'] = $systemPrompt; - - return $self; - } -} diff --git a/src/Sessions/SessionExecuteAgentParams/AgentConfig/Model.php b/src/Sessions/SessionExecuteAgentParams/AgentConfig/Model.php deleted file mode 100644 index 8f5d33a..0000000 --- a/src/Sessions/SessionExecuteAgentParams/AgentConfig/Model.php +++ /dev/null @@ -1,23 +0,0 @@ -|array - */ - public static function variants(): array - { - return ['string', ModelConfig::class]; - } -} diff --git a/src/Sessions/SessionExecuteAgentParams/AgentConfig/Provider.php b/src/Sessions/SessionExecuteAgentParams/AgentConfig/Provider.php deleted file mode 100644 index 9d22eb5..0000000 --- a/src/Sessions/SessionExecuteAgentParams/AgentConfig/Provider.php +++ /dev/null @@ -1,14 +0,0 @@ - */ - use SdkModel; - - /** - * Task for the agent to complete. - */ - #[Required] - public string $instruction; - - /** - * Visually highlight the cursor during actions. - */ - #[Optional] - public ?bool $highlightCursor; - - /** - * Maximum number of steps the agent can take. - */ - #[Optional] - public ?int $maxSteps; - - /** - * `new ExecuteOptions()` is missing required properties by the API. - * - * To enforce required parameters use - * ``` - * ExecuteOptions::with(instruction: ...) - * ``` - * - * Otherwise ensure the following setters are called - * - * ``` - * (new ExecuteOptions)->withInstruction(...) - * ``` - */ - public function __construct() - { - $this->initialize(); - } - - /** - * Construct an instance from the required parameters. - * - * You must use named parameters to construct any parameters with a default value. - */ - public static function with( - string $instruction, - ?bool $highlightCursor = null, - ?int $maxSteps = null - ): self { - $self = new self; - - $self['instruction'] = $instruction; - - null !== $highlightCursor && $self['highlightCursor'] = $highlightCursor; - null !== $maxSteps && $self['maxSteps'] = $maxSteps; - - return $self; - } - - /** - * Task for the agent to complete. - */ - public function withInstruction(string $instruction): self - { - $self = clone $this; - $self['instruction'] = $instruction; - - return $self; - } - - /** - * Visually highlight the cursor during actions. - */ - public function withHighlightCursor(bool $highlightCursor): self - { - $self = clone $this; - $self['highlightCursor'] = $highlightCursor; - - return $self; - } - - /** - * Maximum number of steps the agent can take. - */ - public function withMaxSteps(int $maxSteps): self - { - $self = clone $this; - $self['maxSteps'] = $maxSteps; - - return $self; - } -} diff --git a/src/Sessions/SessionExecuteAgentParams/XStreamResponse.php b/src/Sessions/SessionExecuteAgentParams/XStreamResponse.php deleted file mode 100644 index 29d07e9..0000000 --- a/src/Sessions/SessionExecuteAgentParams/XStreamResponse.php +++ /dev/null @@ -1,12 +0,0 @@ - */ - use SdkModel; - - /** - * Final message from the agent. - */ - #[Optional] - public ?string $message; - - public function __construct() - { - $this->initialize(); - } - - /** - * Construct an instance from the required parameters. - * - * You must use named parameters to construct any parameters with a default value. - */ - public static function with(?string $message = null): self - { - $self = new self; - - null !== $message && $self['message'] = $message; - - return $self; - } - - /** - * Final message from the agent. - */ - public function withMessage(string $message): self - { - $self = clone $this; - $self['message'] = $message; - - return $self; - } -} diff --git a/src/Sessions/SessionExtractParams.php b/src/Sessions/SessionExtractParams.php deleted file mode 100644 index 78fecbd..0000000 --- a/src/Sessions/SessionExtractParams.php +++ /dev/null @@ -1,156 +0,0 @@ -, - * xStreamResponse?: XStreamResponse|value-of, - * } - */ -final class SessionExtractParams implements BaseModel -{ - /** @use SdkModel */ - use SdkModel; - use SdkParams; - - /** - * Frame ID to extract from. - */ - #[Optional('frameId')] - public ?string $frameID; - - /** - * Natural language instruction for extraction. - */ - #[Optional] - public ?string $instruction; - - #[Optional] - public ?Options $options; - - /** - * JSON Schema for structured output. - * - * @var array|null $schema - */ - #[Optional(map: 'mixed')] - public ?array $schema; - - /** @var value-of|null $xStreamResponse */ - #[Optional(enum: XStreamResponse::class)] - public ?string $xStreamResponse; - - public function __construct() - { - $this->initialize(); - } - - /** - * Construct an instance from the required parameters. - * - * You must use named parameters to construct any parameters with a default value. - * - * @param Options|array{ - * model?: ModelConfig|null, selector?: string|null, timeout?: int|null - * } $options - * @param array $schema - * @param XStreamResponse|value-of $xStreamResponse - */ - public static function with( - ?string $frameID = null, - ?string $instruction = null, - Options|array|null $options = null, - ?array $schema = null, - XStreamResponse|string|null $xStreamResponse = null, - ): self { - $self = new self; - - null !== $frameID && $self['frameID'] = $frameID; - null !== $instruction && $self['instruction'] = $instruction; - null !== $options && $self['options'] = $options; - null !== $schema && $self['schema'] = $schema; - null !== $xStreamResponse && $self['xStreamResponse'] = $xStreamResponse; - - return $self; - } - - /** - * Frame ID to extract from. - */ - public function withFrameID(string $frameID): self - { - $self = clone $this; - $self['frameID'] = $frameID; - - return $self; - } - - /** - * Natural language instruction for extraction. - */ - public function withInstruction(string $instruction): self - { - $self = clone $this; - $self['instruction'] = $instruction; - - return $self; - } - - /** - * @param Options|array{ - * model?: ModelConfig|null, selector?: string|null, timeout?: int|null - * } $options - */ - public function withOptions(Options|array $options): self - { - $self = clone $this; - $self['options'] = $options; - - return $self; - } - - /** - * JSON Schema for structured output. - * - * @param array $schema - */ - public function withSchema(array $schema): self - { - $self = clone $this; - $self['schema'] = $schema; - - return $self; - } - - /** - * @param XStreamResponse|value-of $xStreamResponse - */ - public function withXStreamResponse( - XStreamResponse|string $xStreamResponse - ): self { - $self = clone $this; - $self['xStreamResponse'] = $xStreamResponse; - - return $self; - } -} diff --git a/src/Sessions/SessionExtractParams/Options.php b/src/Sessions/SessionExtractParams/Options.php deleted file mode 100644 index 5c8ac6d..0000000 --- a/src/Sessions/SessionExtractParams/Options.php +++ /dev/null @@ -1,100 +0,0 @@ - */ - use SdkModel; - - #[Optional] - public ?ModelConfig $model; - - /** - * Extract only from elements matching this selector. - */ - #[Optional] - public ?string $selector; - - #[Optional] - public ?int $timeout; - - public function __construct() - { - $this->initialize(); - } - - /** - * Construct an instance from the required parameters. - * - * You must use named parameters to construct any parameters with a default value. - * - * @param ModelConfig|array{ - * apiKey?: string|null, - * baseURL?: string|null, - * model?: string|null, - * provider?: value-of|null, - * } $model - */ - public static function with( - ModelConfig|array|null $model = null, - ?string $selector = null, - ?int $timeout = null, - ): self { - $self = new self; - - null !== $model && $self['model'] = $model; - null !== $selector && $self['selector'] = $selector; - null !== $timeout && $self['timeout'] = $timeout; - - return $self; - } - - /** - * @param ModelConfig|array{ - * apiKey?: string|null, - * baseURL?: string|null, - * model?: string|null, - * provider?: value-of|null, - * } $model - */ - public function withModel(ModelConfig|array $model): self - { - $self = clone $this; - $self['model'] = $model; - - return $self; - } - - /** - * Extract only from elements matching this selector. - */ - public function withSelector(string $selector): self - { - $self = clone $this; - $self['selector'] = $selector; - - return $self; - } - - public function withTimeout(int $timeout): self - { - $self = clone $this; - $self['timeout'] = $timeout; - - return $self; - } -} diff --git a/src/Sessions/SessionExtractParams/XStreamResponse.php b/src/Sessions/SessionExtractParams/XStreamResponse.php deleted file mode 100644 index d7052bd..0000000 --- a/src/Sessions/SessionExtractParams/XStreamResponse.php +++ /dev/null @@ -1,12 +0,0 @@ -|array - */ - public static function variants(): array - { - return [Extraction::class, new MapOf('mixed')]; - } -} diff --git a/src/Sessions/SessionExtractResponse/Extraction.php b/src/Sessions/SessionExtractResponse/Extraction.php deleted file mode 100644 index 22a6f95..0000000 --- a/src/Sessions/SessionExtractResponse/Extraction.php +++ /dev/null @@ -1,50 +0,0 @@ - */ - use SdkModel; - - #[Optional] - public ?string $extraction; - - public function __construct() - { - $this->initialize(); - } - - /** - * Construct an instance from the required parameters. - * - * You must use named parameters to construct any parameters with a default value. - */ - public static function with(?string $extraction = null): self - { - $self = new self; - - null !== $extraction && $self['extraction'] = $extraction; - - return $self; - } - - public function withExtraction(string $extraction): self - { - $self = clone $this; - $self['extraction'] = $extraction; - - return $self; - } -} diff --git a/src/Sessions/SessionNavigateParams.php b/src/Sessions/SessionNavigateParams.php deleted file mode 100644 index f3cd37d..0000000 --- a/src/Sessions/SessionNavigateParams.php +++ /dev/null @@ -1,135 +0,0 @@ -|null}, - * xStreamResponse?: XStreamResponse|value-of, - * } - */ -final class SessionNavigateParams implements BaseModel -{ - /** @use SdkModel */ - use SdkModel; - use SdkParams; - - /** - * URL to navigate to. - */ - #[Required] - public string $url; - - #[Optional('frameId')] - public ?string $frameID; - - #[Optional] - public ?Options $options; - - /** @var value-of|null $xStreamResponse */ - #[Optional(enum: XStreamResponse::class)] - public ?string $xStreamResponse; - - /** - * `new SessionNavigateParams()` is missing required properties by the API. - * - * To enforce required parameters use - * ``` - * SessionNavigateParams::with(url: ...) - * ``` - * - * Otherwise ensure the following setters are called - * - * ``` - * (new SessionNavigateParams)->withURL(...) - * ``` - */ - public function __construct() - { - $this->initialize(); - } - - /** - * Construct an instance from the required parameters. - * - * You must use named parameters to construct any parameters with a default value. - * - * @param Options|array{waitUntil?: value-of|null} $options - * @param XStreamResponse|value-of $xStreamResponse - */ - public static function with( - string $url, - ?string $frameID = null, - Options|array|null $options = null, - XStreamResponse|string|null $xStreamResponse = null, - ): self { - $self = new self; - - $self['url'] = $url; - - null !== $frameID && $self['frameID'] = $frameID; - null !== $options && $self['options'] = $options; - null !== $xStreamResponse && $self['xStreamResponse'] = $xStreamResponse; - - return $self; - } - - /** - * URL to navigate to. - */ - public function withURL(string $url): self - { - $self = clone $this; - $self['url'] = $url; - - return $self; - } - - public function withFrameID(string $frameID): self - { - $self = clone $this; - $self['frameID'] = $frameID; - - return $self; - } - - /** - * @param Options|array{waitUntil?: value-of|null} $options - */ - public function withOptions(Options|array $options): self - { - $self = clone $this; - $self['options'] = $options; - - return $self; - } - - /** - * @param XStreamResponse|value-of $xStreamResponse - */ - public function withXStreamResponse( - XStreamResponse|string $xStreamResponse - ): self { - $self = clone $this; - $self['xStreamResponse'] = $xStreamResponse; - - return $self; - } -} diff --git a/src/Sessions/SessionNavigateParams/Options.php b/src/Sessions/SessionNavigateParams/Options.php deleted file mode 100644 index d8cfc0c..0000000 --- a/src/Sessions/SessionNavigateParams/Options.php +++ /dev/null @@ -1,61 +0,0 @@ -|null} - */ -final class Options implements BaseModel -{ - /** @use SdkModel */ - use SdkModel; - - /** - * When to consider navigation complete. - * - * @var value-of|null $waitUntil - */ - #[Optional(enum: WaitUntil::class)] - public ?string $waitUntil; - - public function __construct() - { - $this->initialize(); - } - - /** - * Construct an instance from the required parameters. - * - * You must use named parameters to construct any parameters with a default value. - * - * @param WaitUntil|value-of $waitUntil - */ - public static function with(WaitUntil|string|null $waitUntil = null): self - { - $self = new self; - - null !== $waitUntil && $self['waitUntil'] = $waitUntil; - - return $self; - } - - /** - * When to consider navigation complete. - * - * @param WaitUntil|value-of $waitUntil - */ - public function withWaitUntil(WaitUntil|string $waitUntil): self - { - $self = clone $this; - $self['waitUntil'] = $waitUntil; - - return $self; - } -} diff --git a/src/Sessions/SessionNavigateParams/Options/WaitUntil.php b/src/Sessions/SessionNavigateParams/Options/WaitUntil.php deleted file mode 100644 index 2813cb1..0000000 --- a/src/Sessions/SessionNavigateParams/Options/WaitUntil.php +++ /dev/null @@ -1,17 +0,0 @@ - */ - use SdkModel; - - #[Optional] - public ?bool $ok; - - #[Optional] - public ?int $status; - - #[Optional] - public ?string $url; - - public function __construct() - { - $this->initialize(); - } - - /** - * Construct an instance from the required parameters. - * - * You must use named parameters to construct any parameters with a default value. - */ - public static function with( - ?bool $ok = null, - ?int $status = null, - ?string $url = null - ): self { - $self = new self; - - null !== $ok && $self['ok'] = $ok; - null !== $status && $self['status'] = $status; - null !== $url && $self['url'] = $url; - - return $self; - } - - public function withOk(bool $ok): self - { - $self = clone $this; - $self['ok'] = $ok; - - return $self; - } - - public function withStatus(int $status): self - { - $self = clone $this; - $self['status'] = $status; - - return $self; - } - - public function withURL(string $url): self - { - $self = clone $this; - $self['url'] = $url; - - return $self; - } -} diff --git a/src/Sessions/SessionObserveParams.php b/src/Sessions/SessionObserveParams.php deleted file mode 100644 index 6846de0..0000000 --- a/src/Sessions/SessionObserveParams.php +++ /dev/null @@ -1,131 +0,0 @@ -, - * } - */ -final class SessionObserveParams implements BaseModel -{ - /** @use SdkModel */ - use SdkModel; - use SdkParams; - - /** - * Frame ID to observe. - */ - #[Optional('frameId')] - public ?string $frameID; - - /** - * Natural language instruction to filter actions. - */ - #[Optional] - public ?string $instruction; - - #[Optional] - public ?Options $options; - - /** @var value-of|null $xStreamResponse */ - #[Optional(enum: XStreamResponse::class)] - public ?string $xStreamResponse; - - public function __construct() - { - $this->initialize(); - } - - /** - * Construct an instance from the required parameters. - * - * You must use named parameters to construct any parameters with a default value. - * - * @param Options|array{ - * model?: ModelConfig|null, selector?: string|null, timeout?: int|null - * } $options - * @param XStreamResponse|value-of $xStreamResponse - */ - public static function with( - ?string $frameID = null, - ?string $instruction = null, - Options|array|null $options = null, - XStreamResponse|string|null $xStreamResponse = null, - ): self { - $self = new self; - - null !== $frameID && $self['frameID'] = $frameID; - null !== $instruction && $self['instruction'] = $instruction; - null !== $options && $self['options'] = $options; - null !== $xStreamResponse && $self['xStreamResponse'] = $xStreamResponse; - - return $self; - } - - /** - * Frame ID to observe. - */ - public function withFrameID(string $frameID): self - { - $self = clone $this; - $self['frameID'] = $frameID; - - return $self; - } - - /** - * Natural language instruction to filter actions. - */ - public function withInstruction(string $instruction): self - { - $self = clone $this; - $self['instruction'] = $instruction; - - return $self; - } - - /** - * @param Options|array{ - * model?: ModelConfig|null, selector?: string|null, timeout?: int|null - * } $options - */ - public function withOptions(Options|array $options): self - { - $self = clone $this; - $self['options'] = $options; - - return $self; - } - - /** - * @param XStreamResponse|value-of $xStreamResponse - */ - public function withXStreamResponse( - XStreamResponse|string $xStreamResponse - ): self { - $self = clone $this; - $self['xStreamResponse'] = $xStreamResponse; - - return $self; - } -} diff --git a/src/Sessions/SessionObserveParams/Options.php b/src/Sessions/SessionObserveParams/Options.php deleted file mode 100644 index edf0b99..0000000 --- a/src/Sessions/SessionObserveParams/Options.php +++ /dev/null @@ -1,100 +0,0 @@ - */ - use SdkModel; - - #[Optional] - public ?ModelConfig $model; - - /** - * Observe only elements matching this selector. - */ - #[Optional] - public ?string $selector; - - #[Optional] - public ?int $timeout; - - public function __construct() - { - $this->initialize(); - } - - /** - * Construct an instance from the required parameters. - * - * You must use named parameters to construct any parameters with a default value. - * - * @param ModelConfig|array{ - * apiKey?: string|null, - * baseURL?: string|null, - * model?: string|null, - * provider?: value-of|null, - * } $model - */ - public static function with( - ModelConfig|array|null $model = null, - ?string $selector = null, - ?int $timeout = null, - ): self { - $self = new self; - - null !== $model && $self['model'] = $model; - null !== $selector && $self['selector'] = $selector; - null !== $timeout && $self['timeout'] = $timeout; - - return $self; - } - - /** - * @param ModelConfig|array{ - * apiKey?: string|null, - * baseURL?: string|null, - * model?: string|null, - * provider?: value-of|null, - * } $model - */ - public function withModel(ModelConfig|array $model): self - { - $self = clone $this; - $self['model'] = $model; - - return $self; - } - - /** - * Observe only elements matching this selector. - */ - public function withSelector(string $selector): self - { - $self = clone $this; - $self['selector'] = $selector; - - return $self; - } - - public function withTimeout(int $timeout): self - { - $self = clone $this; - $self['timeout'] = $timeout; - - return $self; - } -} diff --git a/src/Sessions/SessionObserveParams/XStreamResponse.php b/src/Sessions/SessionObserveParams/XStreamResponse.php deleted file mode 100644 index 5a45103..0000000 --- a/src/Sessions/SessionObserveParams/XStreamResponse.php +++ /dev/null @@ -1,12 +0,0 @@ -withBrowserbaseAPIKey(...) - * ->withBrowserbaseProjectID(...) - * ``` - */ public function __construct() { $this->initialize(); @@ -101,101 +54,59 @@ public function __construct() * You must use named parameters to construct any parameters with a default value. */ public static function with( - string $browserbaseAPIKey, - string $browserbaseProjectID, - ?int $domSettleTimeout = null, - ?string $model = null, - ?bool $selfHeal = null, - ?string $systemPrompt = null, - ?int $verbose = null, + mixed $body = null, + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, ): self { $self = new self; - $self['browserbaseAPIKey'] = $browserbaseAPIKey; - $self['browserbaseProjectID'] = $browserbaseProjectID; - - null !== $domSettleTimeout && $self['domSettleTimeout'] = $domSettleTimeout; - null !== $model && $self['model'] = $model; - null !== $selfHeal && $self['selfHeal'] = $selfHeal; - null !== $systemPrompt && $self['systemPrompt'] = $systemPrompt; - null !== $verbose && $self['verbose'] = $verbose; - - return $self; - } - - /** - * API key for Browserbase Cloud. - */ - public function withBrowserbaseAPIKey(string $browserbaseAPIKey): self - { - $self = clone $this; - $self['browserbaseAPIKey'] = $browserbaseAPIKey; - - return $self; - } - - /** - * Project ID for Browserbase. - */ - public function withBrowserbaseProjectID(string $browserbaseProjectID): self - { - $self = clone $this; - $self['browserbaseProjectID'] = $browserbaseProjectID; + null !== $body && $self['body'] = $body; + null !== $xLanguage && $self['xLanguage'] = $xLanguage; + null !== $xSDKVersion && $self['xSDKVersion'] = $xSDKVersion; + null !== $xSentAt && $self['xSentAt'] = $xSentAt; + null !== $xStreamResponse && $self['xStreamResponse'] = $xStreamResponse; return $self; } - /** - * Timeout in ms to wait for DOM to settle. - */ - public function withDomSettleTimeout(int $domSettleTimeout): self + public function withBody(mixed $body): self { $self = clone $this; - $self['domSettleTimeout'] = $domSettleTimeout; + $self['body'] = $body; return $self; } - /** - * AI model to use for actions (must be prefixed with provider/). - */ - public function withModel(string $model): self + public function withXLanguage(mixed $xLanguage): self { $self = clone $this; - $self['model'] = $model; + $self['xLanguage'] = $xLanguage; return $self; } - /** - * Enable self-healing for failed actions. - */ - public function withSelfHeal(bool $selfHeal): self + public function withXSDKVersion(mixed $xSDKVersion): self { $self = clone $this; - $self['selfHeal'] = $selfHeal; + $self['xSDKVersion'] = $xSDKVersion; return $self; } - /** - * Custom system prompt for AI actions. - */ - public function withSystemPrompt(string $systemPrompt): self + public function withXSentAt(mixed $xSentAt): self { $self = clone $this; - $self['systemPrompt'] = $systemPrompt; + $self['xSentAt'] = $xSentAt; return $self; } - /** - * Logging verbosity level. - */ - public function withVerbose(int $verbose): self + public function withXStreamResponse(mixed $xStreamResponse): self { $self = clone $this; - $self['verbose'] = $verbose; + $self['xStreamResponse'] = $xStreamResponse; return $self; } diff --git a/src/Sessions/SessionStartResponse.php b/src/Sessions/SessionStartResponse.php deleted file mode 100644 index 4c3d861..0000000 --- a/src/Sessions/SessionStartResponse.php +++ /dev/null @@ -1,88 +0,0 @@ - */ - use SdkModel; - - /** - * Whether the session is ready to use. - */ - #[Required] - public bool $available; - - /** - * Unique identifier for the session. - */ - #[Required('sessionId')] - public string $sessionID; - - /** - * `new SessionStartResponse()` is missing required properties by the API. - * - * To enforce required parameters use - * ``` - * SessionStartResponse::with(available: ..., sessionID: ...) - * ``` - * - * Otherwise ensure the following setters are called - * - * ``` - * (new SessionStartResponse)->withAvailable(...)->withSessionID(...) - * ``` - */ - public function __construct() - { - $this->initialize(); - } - - /** - * Construct an instance from the required parameters. - * - * You must use named parameters to construct any parameters with a default value. - */ - public static function with(bool $available, string $sessionID): self - { - $self = new self; - - $self['available'] = $available; - $self['sessionID'] = $sessionID; - - return $self; - } - - /** - * Whether the session is ready to use. - */ - public function withAvailable(bool $available): self - { - $self = clone $this; - $self['available'] = $available; - - return $self; - } - - /** - * Unique identifier for the session. - */ - public function withSessionID(string $sessionID): self - { - $self = clone $this; - $self['sessionID'] = $sessionID; - - return $self; - } -} diff --git a/tests/Services/SessionsTest.php b/tests/Services/SessionsTest.php index 684dd57..af48882 100644 --- a/tests/Services/SessionsTest.php +++ b/tests/Services/SessionsTest.php @@ -6,11 +6,6 @@ use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Stagehand\Client; -use Stagehand\Sessions\SessionActResponse; -use Stagehand\Sessions\SessionEndResponse; -use Stagehand\Sessions\SessionExecuteAgentResponse; -use Stagehand\Sessions\SessionNavigateResponse; -use Stagehand\Sessions\SessionStartResponse; use Tests\UnsupportedMockTests; /** @@ -36,175 +31,6 @@ protected function setUp(): void $this->client = $client; } - #[Test] - public function testAct(): void - { - if (UnsupportedMockTests::$skip) { - $this->markTestSkipped('Prism tests are disabled'); - } - - $result = $this->client->sessions->act( - '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', - input: 'click the sign in button' - ); - - // @phpstan-ignore-next-line method.alreadyNarrowedType - $this->assertInstanceOf(SessionActResponse::class, $result); - } - - #[Test] - public function testActWithOptionalParams(): void - { - if (UnsupportedMockTests::$skip) { - $this->markTestSkipped('Prism tests are disabled'); - } - - $result = $this->client->sessions->act( - '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', - input: 'click the sign in button', - frameID: 'frameId', - options: [ - 'model' => [ - 'apiKey' => 'apiKey', - 'baseURL' => 'https://example.com', - 'model' => 'model', - 'provider' => 'openai', - ], - 'timeout' => 0, - 'variables' => ['foo' => 'string'], - ], - xStreamResponse: 'true', - ); - - // @phpstan-ignore-next-line method.alreadyNarrowedType - $this->assertInstanceOf(SessionActResponse::class, $result); - } - - #[Test] - public function testEnd(): void - { - if (UnsupportedMockTests::$skip) { - $this->markTestSkipped('Prism tests are disabled'); - } - - $result = $this->client->sessions->end( - '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e' - ); - - // @phpstan-ignore-next-line method.alreadyNarrowedType - $this->assertInstanceOf(SessionEndResponse::class, $result); - } - - #[Test] - public function testExecuteAgent(): void - { - if (UnsupportedMockTests::$skip) { - $this->markTestSkipped('Prism tests are disabled'); - } - - $result = $this->client->sessions->executeAgent( - '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', - agentConfig: [], - executeOptions: ['instruction' => 'Find and click the first product'], - ); - - // @phpstan-ignore-next-line method.alreadyNarrowedType - $this->assertInstanceOf(SessionExecuteAgentResponse::class, $result); - } - - #[Test] - public function testExecuteAgentWithOptionalParams(): void - { - if (UnsupportedMockTests::$skip) { - $this->markTestSkipped('Prism tests are disabled'); - } - - $result = $this->client->sessions->executeAgent( - '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', - agentConfig: [ - 'cua' => true, - 'model' => 'openai/gpt-4o', - 'provider' => 'openai', - 'systemPrompt' => 'systemPrompt', - ], - executeOptions: [ - 'instruction' => 'Find and click the first product', - 'highlightCursor' => true, - 'maxSteps' => 10, - ], - frameID: 'frameId', - xStreamResponse: 'true', - ); - - // @phpstan-ignore-next-line method.alreadyNarrowedType - $this->assertInstanceOf(SessionExecuteAgentResponse::class, $result); - } - - #[Test] - public function testExtract(): void - { - if (UnsupportedMockTests::$skip) { - $this->markTestSkipped('Prism tests are disabled'); - } - - $result = $this->client->sessions->extract( - '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e' - ); - - // @phpstan-ignore-next-line method.alreadyNarrowedType - $this->assertNotNull($result); - } - - #[Test] - public function testNavigate(): void - { - if (UnsupportedMockTests::$skip) { - $this->markTestSkipped('Prism tests are disabled'); - } - - $result = $this->client->sessions->navigate( - '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', - url: 'https://example.com' - ); - - // @phpstan-ignore-next-line method.alreadyNarrowedType - $this->assertInstanceOf(SessionNavigateResponse::class, $result); - } - - #[Test] - public function testNavigateWithOptionalParams(): void - { - if (UnsupportedMockTests::$skip) { - $this->markTestSkipped('Prism tests are disabled'); - } - - $result = $this->client->sessions->navigate( - '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', - url: 'https://example.com', - frameID: 'frameId', - options: ['waitUntil' => 'load'], - xStreamResponse: 'true', - ); - - // @phpstan-ignore-next-line method.alreadyNarrowedType - $this->assertInstanceOf(SessionNavigateResponse::class, $result); - } - - #[Test] - public function testObserve(): void - { - if (UnsupportedMockTests::$skip) { - $this->markTestSkipped('Prism tests are disabled'); - } - - $result = $this->client->sessions->observe( - '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e' - ); - - // @phpstan-ignore-next-line method.alreadyNarrowedType - $this->assertIsList($result); - } - #[Test] public function testStart(): void { @@ -212,33 +38,9 @@ public function testStart(): void $this->markTestSkipped('Prism tests are disabled'); } - $result = $this->client->sessions->start( - browserbaseAPIKey: 'BROWSERBASE_API_KEY', - browserbaseProjectID: 'BROWSERBASE_PROJECT_ID', - ); - - // @phpstan-ignore-next-line method.alreadyNarrowedType - $this->assertInstanceOf(SessionStartResponse::class, $result); - } - - #[Test] - public function testStartWithOptionalParams(): void - { - if (UnsupportedMockTests::$skip) { - $this->markTestSkipped('Prism tests are disabled'); - } - - $result = $this->client->sessions->start( - browserbaseAPIKey: 'BROWSERBASE_API_KEY', - browserbaseProjectID: 'BROWSERBASE_PROJECT_ID', - domSettleTimeout: 0, - model: 'openai/gpt-4o', - selfHeal: true, - systemPrompt: 'systemPrompt', - verbose: 1, - ); + $result = $this->client->sessions->start(); // @phpstan-ignore-next-line method.alreadyNarrowedType - $this->assertInstanceOf(SessionStartResponse::class, $result); + $this->assertIsNotResource($result); } } From 4062155567a99093e39cbf101193805df0002895 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 02:15:52 +0000 Subject: [PATCH 02/29] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index f5e93e0..855c5aa 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 1 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-516862e7e90968bc55ac44ce7ffe2d5c1f738c11757471c2b9e0e4cff9384f2c.yml -openapi_spec_hash: 19bbe52a6ae0eec7fc3f6698e831ee55 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-24dc965121b5ad70c846fd8b96ce4638d13bac7e86ba0f50a8d13a5664ac4929.yml +openapi_spec_hash: 5a8e70d2a5358bfd6917f907b4a4d1f3 config_hash: a35b56eb05306a0f02e83c11d57f975f From 9c9d8f74c362253e3494407a8de53713079ff3d9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 02:41:00 +0000 Subject: [PATCH 03/29] feat(api): manual updates --- .stats.yml | 8 +- src/ServiceContracts/SessionsContract.php | 130 +++++++++ src/ServiceContracts/SessionsRawContract.php | 102 +++++++ src/Services/SessionsRawService.php | 286 +++++++++++++++++++ src/Services/SessionsService.php | 231 +++++++++++++++ src/Sessions/SessionActParams.php | 113 ++++++++ src/Sessions/SessionEndParams.php | 99 +++++++ src/Sessions/SessionExecuteAgentParams.php | 113 ++++++++ src/Sessions/SessionExtractParams.php | 113 ++++++++ src/Sessions/SessionNavigateParams.php | 113 ++++++++ src/Sessions/SessionObserveParams.php | 113 ++++++++ tests/Services/SessionsTest.php | 78 +++++ 12 files changed, 1495 insertions(+), 4 deletions(-) create mode 100644 src/Sessions/SessionActParams.php create mode 100644 src/Sessions/SessionEndParams.php create mode 100644 src/Sessions/SessionExecuteAgentParams.php create mode 100644 src/Sessions/SessionExtractParams.php create mode 100644 src/Sessions/SessionNavigateParams.php create mode 100644 src/Sessions/SessionObserveParams.php diff --git a/.stats.yml b/.stats.yml index 855c5aa..c436ede 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 1 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-24dc965121b5ad70c846fd8b96ce4638d13bac7e86ba0f50a8d13a5664ac4929.yml -openapi_spec_hash: 5a8e70d2a5358bfd6917f907b4a4d1f3 -config_hash: a35b56eb05306a0f02e83c11d57f975f +configured_endpoints: 7 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-c1a6f03afe5d6823c198e5ac476fb688dacc783dae1fefdf6bf142084e298e16.yml +openapi_spec_hash: d20e8f697ce8d5bb80295fc1e8ce02e8 +config_hash: e457d704d820df5d25acfd379169f132 diff --git a/src/ServiceContracts/SessionsContract.php b/src/ServiceContracts/SessionsContract.php index f333136..941b801 100644 --- a/src/ServiceContracts/SessionsContract.php +++ b/src/ServiceContracts/SessionsContract.php @@ -9,6 +9,136 @@ interface SessionsContract { + /** + * @api + * + * @param mixed $id Path param: Unique session identifier + * @param mixed $body Body param: + * @param mixed $xLanguage Header param: Client SDK language + * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK + * @param mixed $xSentAt Header param: ISO timestamp when request was sent + * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * + * @throws APIException + */ + public function act( + mixed $id, + mixed $body = null, + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, + ?RequestOptions $requestOptions = null, + ): mixed; + + /** + * @api + * + * @param mixed $id Unique session identifier + * @param mixed $xLanguage Client SDK language + * @param mixed $xSDKVersion Version of the Stagehand SDK + * @param mixed $xSentAt ISO timestamp when request was sent + * @param mixed $xStreamResponse Whether to stream the response via SSE + * + * @throws APIException + */ + public function end( + mixed $id, + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, + ?RequestOptions $requestOptions = null, + ): mixed; + + /** + * @api + * + * @param mixed $id Path param: Unique session identifier + * @param mixed $body Body param: + * @param mixed $xLanguage Header param: Client SDK language + * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK + * @param mixed $xSentAt Header param: ISO timestamp when request was sent + * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * + * @throws APIException + */ + public function executeAgent( + mixed $id, + mixed $body = null, + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, + ?RequestOptions $requestOptions = null, + ): mixed; + + /** + * @api + * + * @param mixed $id Path param: Unique session identifier + * @param mixed $body Body param: + * @param mixed $xLanguage Header param: Client SDK language + * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK + * @param mixed $xSentAt Header param: ISO timestamp when request was sent + * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * + * @throws APIException + */ + public function extract( + mixed $id, + mixed $body = null, + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, + ?RequestOptions $requestOptions = null, + ): mixed; + + /** + * @api + * + * @param mixed $id Path param: Unique session identifier + * @param mixed $body Body param: + * @param mixed $xLanguage Header param: Client SDK language + * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK + * @param mixed $xSentAt Header param: ISO timestamp when request was sent + * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * + * @throws APIException + */ + public function navigate( + mixed $id, + mixed $body = null, + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, + ?RequestOptions $requestOptions = null, + ): mixed; + + /** + * @api + * + * @param mixed $id Path param: Unique session identifier + * @param mixed $body Body param: + * @param mixed $xLanguage Header param: Client SDK language + * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK + * @param mixed $xSentAt Header param: ISO timestamp when request was sent + * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * + * @throws APIException + */ + public function observe( + mixed $id, + mixed $body = null, + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, + ?RequestOptions $requestOptions = null, + ): mixed; + /** * @api * diff --git a/src/ServiceContracts/SessionsRawContract.php b/src/ServiceContracts/SessionsRawContract.php index fd03a94..defe127 100644 --- a/src/ServiceContracts/SessionsRawContract.php +++ b/src/ServiceContracts/SessionsRawContract.php @@ -7,10 +7,112 @@ use Stagehand\Core\Contracts\BaseResponse; use Stagehand\Core\Exceptions\APIException; use Stagehand\RequestOptions; +use Stagehand\Sessions\SessionActParams; +use Stagehand\Sessions\SessionEndParams; +use Stagehand\Sessions\SessionExecuteAgentParams; +use Stagehand\Sessions\SessionExtractParams; +use Stagehand\Sessions\SessionNavigateParams; +use Stagehand\Sessions\SessionObserveParams; use Stagehand\Sessions\SessionStartParams; interface SessionsRawContract { + /** + * @api + * + * @param mixed $id Path param: Unique session identifier + * @param array|SessionActParams $params + * + * @return BaseResponse + * + * @throws APIException + */ + public function act( + mixed $id, + array|SessionActParams $params, + ?RequestOptions $requestOptions = null, + ): BaseResponse; + + /** + * @api + * + * @param mixed $id Unique session identifier + * @param array|SessionEndParams $params + * + * @return BaseResponse + * + * @throws APIException + */ + public function end( + mixed $id, + array|SessionEndParams $params, + ?RequestOptions $requestOptions = null, + ): BaseResponse; + + /** + * @api + * + * @param mixed $id Path param: Unique session identifier + * @param array|SessionExecuteAgentParams $params + * + * @return BaseResponse + * + * @throws APIException + */ + public function executeAgent( + mixed $id, + array|SessionExecuteAgentParams $params, + ?RequestOptions $requestOptions = null, + ): BaseResponse; + + /** + * @api + * + * @param mixed $id Path param: Unique session identifier + * @param array|SessionExtractParams $params + * + * @return BaseResponse + * + * @throws APIException + */ + public function extract( + mixed $id, + array|SessionExtractParams $params, + ?RequestOptions $requestOptions = null, + ): BaseResponse; + + /** + * @api + * + * @param mixed $id Path param: Unique session identifier + * @param array|SessionNavigateParams $params + * + * @return BaseResponse + * + * @throws APIException + */ + public function navigate( + mixed $id, + array|SessionNavigateParams $params, + ?RequestOptions $requestOptions = null, + ): BaseResponse; + + /** + * @api + * + * @param mixed $id Path param: Unique session identifier + * @param array|SessionObserveParams $params + * + * @return BaseResponse + * + * @throws APIException + */ + public function observe( + mixed $id, + array|SessionObserveParams $params, + ?RequestOptions $requestOptions = null, + ): BaseResponse; + /** * @api * diff --git a/src/Services/SessionsRawService.php b/src/Services/SessionsRawService.php index 72184cd..60f668d 100644 --- a/src/Services/SessionsRawService.php +++ b/src/Services/SessionsRawService.php @@ -10,6 +10,12 @@ use Stagehand\Core\Util; use Stagehand\RequestOptions; use Stagehand\ServiceContracts\SessionsRawContract; +use Stagehand\Sessions\SessionActParams; +use Stagehand\Sessions\SessionEndParams; +use Stagehand\Sessions\SessionExecuteAgentParams; +use Stagehand\Sessions\SessionExtractParams; +use Stagehand\Sessions\SessionNavigateParams; +use Stagehand\Sessions\SessionObserveParams; use Stagehand\Sessions\SessionStartParams; final class SessionsRawService implements SessionsRawContract @@ -20,6 +26,286 @@ final class SessionsRawService implements SessionsRawContract */ public function __construct(private Client $client) {} + /** + * @api + * + * Executes a browser action using natural language instructions or a predefined Action object. + * + * @param mixed $id Path param: Unique session identifier + * @param array{ + * body?: mixed, + * xLanguage?: mixed, + * xSDKVersion?: mixed, + * xSentAt?: mixed, + * xStreamResponse?: mixed, + * }|SessionActParams $params + * + * @return BaseResponse + * + * @throws APIException + */ + public function act( + mixed $id, + array|SessionActParams $params, + ?RequestOptions $requestOptions = null, + ): BaseResponse { + [$parsed, $options] = SessionActParams::parseRequest( + $params, + $requestOptions, + ); + + // @phpstan-ignore-next-line return.type + return $this->client->request( + method: 'post', + path: ['sessions/%1$s/act', $id], + headers: Util::array_transform_keys( + array_diff_key($parsed, array_flip(['body'])), + [ + 'xLanguage' => 'x-language', + 'xSDKVersion' => 'x-sdk-version', + 'xSentAt' => 'x-sent-at', + 'xStreamResponse' => 'x-stream-response', + ], + ), + body: $parsed['body'], + options: $options, + convert: 'mixed', + ); + } + + /** + * @api + * + * Terminates the browser session and releases all associated resources. + * + * @param mixed $id Unique session identifier + * @param array{ + * xLanguage?: mixed, + * xSDKVersion?: mixed, + * xSentAt?: mixed, + * xStreamResponse?: mixed, + * }|SessionEndParams $params + * + * @return BaseResponse + * + * @throws APIException + */ + public function end( + mixed $id, + array|SessionEndParams $params, + ?RequestOptions $requestOptions = null, + ): BaseResponse { + [$parsed, $options] = SessionEndParams::parseRequest( + $params, + $requestOptions, + ); + + // @phpstan-ignore-next-line return.type + return $this->client->request( + method: 'post', + path: ['sessions/%1$s/end', $id], + headers: Util::array_transform_keys( + $parsed, + [ + 'xLanguage' => 'x-language', + 'xSDKVersion' => 'x-sdk-version', + 'xSentAt' => 'x-sent-at', + 'xStreamResponse' => 'x-stream-response', + ], + ), + options: $options, + convert: 'mixed', + ); + } + + /** + * @api + * + * Runs an autonomous AI agent that can perform complex multi-step browser tasks. + * + * @param mixed $id Path param: Unique session identifier + * @param array{ + * body?: mixed, + * xLanguage?: mixed, + * xSDKVersion?: mixed, + * xSentAt?: mixed, + * xStreamResponse?: mixed, + * }|SessionExecuteAgentParams $params + * + * @return BaseResponse + * + * @throws APIException + */ + public function executeAgent( + mixed $id, + array|SessionExecuteAgentParams $params, + ?RequestOptions $requestOptions = null, + ): BaseResponse { + [$parsed, $options] = SessionExecuteAgentParams::parseRequest( + $params, + $requestOptions, + ); + + // @phpstan-ignore-next-line return.type + return $this->client->request( + method: 'post', + path: ['sessions/%1$s/agentExecute', $id], + headers: Util::array_transform_keys( + array_diff_key($parsed, array_flip(['body'])), + [ + 'xLanguage' => 'x-language', + 'xSDKVersion' => 'x-sdk-version', + 'xSentAt' => 'x-sent-at', + 'xStreamResponse' => 'x-stream-response', + ], + ), + body: $parsed['body'], + options: $options, + convert: 'mixed', + ); + } + + /** + * @api + * + * Extracts structured data from the current page using AI-powered analysis. + * + * @param mixed $id Path param: Unique session identifier + * @param array{ + * body?: mixed, + * xLanguage?: mixed, + * xSDKVersion?: mixed, + * xSentAt?: mixed, + * xStreamResponse?: mixed, + * }|SessionExtractParams $params + * + * @return BaseResponse + * + * @throws APIException + */ + public function extract( + mixed $id, + array|SessionExtractParams $params, + ?RequestOptions $requestOptions = null, + ): BaseResponse { + [$parsed, $options] = SessionExtractParams::parseRequest( + $params, + $requestOptions, + ); + + // @phpstan-ignore-next-line return.type + return $this->client->request( + method: 'post', + path: ['sessions/%1$s/extract', $id], + headers: Util::array_transform_keys( + array_diff_key($parsed, array_flip(['body'])), + [ + 'xLanguage' => 'x-language', + 'xSDKVersion' => 'x-sdk-version', + 'xSentAt' => 'x-sent-at', + 'xStreamResponse' => 'x-stream-response', + ], + ), + body: $parsed['body'], + options: $options, + convert: 'mixed', + ); + } + + /** + * @api + * + * Navigates the browser to the specified URL. + * + * @param mixed $id Path param: Unique session identifier + * @param array{ + * body?: mixed, + * xLanguage?: mixed, + * xSDKVersion?: mixed, + * xSentAt?: mixed, + * xStreamResponse?: mixed, + * }|SessionNavigateParams $params + * + * @return BaseResponse + * + * @throws APIException + */ + public function navigate( + mixed $id, + array|SessionNavigateParams $params, + ?RequestOptions $requestOptions = null, + ): BaseResponse { + [$parsed, $options] = SessionNavigateParams::parseRequest( + $params, + $requestOptions, + ); + + // @phpstan-ignore-next-line return.type + return $this->client->request( + method: 'post', + path: ['sessions/%1$s/navigate', $id], + headers: Util::array_transform_keys( + array_diff_key($parsed, array_flip(['body'])), + [ + 'xLanguage' => 'x-language', + 'xSDKVersion' => 'x-sdk-version', + 'xSentAt' => 'x-sent-at', + 'xStreamResponse' => 'x-stream-response', + ], + ), + body: $parsed['body'], + options: $options, + convert: 'mixed', + ); + } + + /** + * @api + * + * Identifies and returns available actions on the current page that match the given instruction. + * + * @param mixed $id Path param: Unique session identifier + * @param array{ + * body?: mixed, + * xLanguage?: mixed, + * xSDKVersion?: mixed, + * xSentAt?: mixed, + * xStreamResponse?: mixed, + * }|SessionObserveParams $params + * + * @return BaseResponse + * + * @throws APIException + */ + public function observe( + mixed $id, + array|SessionObserveParams $params, + ?RequestOptions $requestOptions = null, + ): BaseResponse { + [$parsed, $options] = SessionObserveParams::parseRequest( + $params, + $requestOptions, + ); + + // @phpstan-ignore-next-line return.type + return $this->client->request( + method: 'post', + path: ['sessions/%1$s/observe', $id], + headers: Util::array_transform_keys( + array_diff_key($parsed, array_flip(['body'])), + [ + 'xLanguage' => 'x-language', + 'xSDKVersion' => 'x-sdk-version', + 'xSentAt' => 'x-sent-at', + 'xStreamResponse' => 'x-stream-response', + ], + ), + body: $parsed['body'], + options: $options, + convert: 'mixed', + ); + } + /** * @api * diff --git a/src/Services/SessionsService.php b/src/Services/SessionsService.php index 0ae7461..68f73c7 100644 --- a/src/Services/SessionsService.php +++ b/src/Services/SessionsService.php @@ -25,6 +25,237 @@ public function __construct(private Client $client) $this->raw = new SessionsRawService($client); } + /** + * @api + * + * Executes a browser action using natural language instructions or a predefined Action object. + * + * @param mixed $id Path param: Unique session identifier + * @param mixed $body Body param: + * @param mixed $xLanguage Header param: Client SDK language + * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK + * @param mixed $xSentAt Header param: ISO timestamp when request was sent + * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * + * @throws APIException + */ + public function act( + mixed $id, + mixed $body = null, + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, + ?RequestOptions $requestOptions = null, + ): mixed { + $params = Util::removeNulls( + [ + 'body' => $body, + 'xLanguage' => $xLanguage, + 'xSDKVersion' => $xSDKVersion, + 'xSentAt' => $xSentAt, + 'xStreamResponse' => $xStreamResponse, + ], + ); + + // @phpstan-ignore-next-line argument.type + $response = $this->raw->act($id, params: $params, requestOptions: $requestOptions); + + return $response->parse(); + } + + /** + * @api + * + * Terminates the browser session and releases all associated resources. + * + * @param mixed $id Unique session identifier + * @param mixed $xLanguage Client SDK language + * @param mixed $xSDKVersion Version of the Stagehand SDK + * @param mixed $xSentAt ISO timestamp when request was sent + * @param mixed $xStreamResponse Whether to stream the response via SSE + * + * @throws APIException + */ + public function end( + mixed $id, + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, + ?RequestOptions $requestOptions = null, + ): mixed { + $params = Util::removeNulls( + [ + 'xLanguage' => $xLanguage, + 'xSDKVersion' => $xSDKVersion, + 'xSentAt' => $xSentAt, + 'xStreamResponse' => $xStreamResponse, + ], + ); + + // @phpstan-ignore-next-line argument.type + $response = $this->raw->end($id, params: $params, requestOptions: $requestOptions); + + return $response->parse(); + } + + /** + * @api + * + * Runs an autonomous AI agent that can perform complex multi-step browser tasks. + * + * @param mixed $id Path param: Unique session identifier + * @param mixed $body Body param: + * @param mixed $xLanguage Header param: Client SDK language + * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK + * @param mixed $xSentAt Header param: ISO timestamp when request was sent + * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * + * @throws APIException + */ + public function executeAgent( + mixed $id, + mixed $body = null, + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, + ?RequestOptions $requestOptions = null, + ): mixed { + $params = Util::removeNulls( + [ + 'body' => $body, + 'xLanguage' => $xLanguage, + 'xSDKVersion' => $xSDKVersion, + 'xSentAt' => $xSentAt, + 'xStreamResponse' => $xStreamResponse, + ], + ); + + // @phpstan-ignore-next-line argument.type + $response = $this->raw->executeAgent($id, params: $params, requestOptions: $requestOptions); + + return $response->parse(); + } + + /** + * @api + * + * Extracts structured data from the current page using AI-powered analysis. + * + * @param mixed $id Path param: Unique session identifier + * @param mixed $body Body param: + * @param mixed $xLanguage Header param: Client SDK language + * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK + * @param mixed $xSentAt Header param: ISO timestamp when request was sent + * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * + * @throws APIException + */ + public function extract( + mixed $id, + mixed $body = null, + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, + ?RequestOptions $requestOptions = null, + ): mixed { + $params = Util::removeNulls( + [ + 'body' => $body, + 'xLanguage' => $xLanguage, + 'xSDKVersion' => $xSDKVersion, + 'xSentAt' => $xSentAt, + 'xStreamResponse' => $xStreamResponse, + ], + ); + + // @phpstan-ignore-next-line argument.type + $response = $this->raw->extract($id, params: $params, requestOptions: $requestOptions); + + return $response->parse(); + } + + /** + * @api + * + * Navigates the browser to the specified URL. + * + * @param mixed $id Path param: Unique session identifier + * @param mixed $body Body param: + * @param mixed $xLanguage Header param: Client SDK language + * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK + * @param mixed $xSentAt Header param: ISO timestamp when request was sent + * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * + * @throws APIException + */ + public function navigate( + mixed $id, + mixed $body = null, + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, + ?RequestOptions $requestOptions = null, + ): mixed { + $params = Util::removeNulls( + [ + 'body' => $body, + 'xLanguage' => $xLanguage, + 'xSDKVersion' => $xSDKVersion, + 'xSentAt' => $xSentAt, + 'xStreamResponse' => $xStreamResponse, + ], + ); + + // @phpstan-ignore-next-line argument.type + $response = $this->raw->navigate($id, params: $params, requestOptions: $requestOptions); + + return $response->parse(); + } + + /** + * @api + * + * Identifies and returns available actions on the current page that match the given instruction. + * + * @param mixed $id Path param: Unique session identifier + * @param mixed $body Body param: + * @param mixed $xLanguage Header param: Client SDK language + * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK + * @param mixed $xSentAt Header param: ISO timestamp when request was sent + * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * + * @throws APIException + */ + public function observe( + mixed $id, + mixed $body = null, + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, + ?RequestOptions $requestOptions = null, + ): mixed { + $params = Util::removeNulls( + [ + 'body' => $body, + 'xLanguage' => $xLanguage, + 'xSDKVersion' => $xSDKVersion, + 'xSentAt' => $xSentAt, + 'xStreamResponse' => $xStreamResponse, + ], + ); + + // @phpstan-ignore-next-line argument.type + $response = $this->raw->observe($id, params: $params, requestOptions: $requestOptions); + + return $response->parse(); + } + /** * @api * diff --git a/src/Sessions/SessionActParams.php b/src/Sessions/SessionActParams.php new file mode 100644 index 0000000..a1240b1 --- /dev/null +++ b/src/Sessions/SessionActParams.php @@ -0,0 +1,113 @@ + */ + use SdkModel; + use SdkParams; + + #[Optional] + public mixed $body; + + #[Optional] + public mixed $xLanguage; + + #[Optional] + public mixed $xSDKVersion; + + #[Optional] + public mixed $xSentAt; + + #[Optional] + public mixed $xStreamResponse; + + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with( + mixed $body = null, + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, + ): self { + $self = new self; + + null !== $body && $self['body'] = $body; + null !== $xLanguage && $self['xLanguage'] = $xLanguage; + null !== $xSDKVersion && $self['xSDKVersion'] = $xSDKVersion; + null !== $xSentAt && $self['xSentAt'] = $xSentAt; + null !== $xStreamResponse && $self['xStreamResponse'] = $xStreamResponse; + + return $self; + } + + public function withBody(mixed $body): self + { + $self = clone $this; + $self['body'] = $body; + + return $self; + } + + public function withXLanguage(mixed $xLanguage): self + { + $self = clone $this; + $self['xLanguage'] = $xLanguage; + + return $self; + } + + public function withXSDKVersion(mixed $xSDKVersion): self + { + $self = clone $this; + $self['xSDKVersion'] = $xSDKVersion; + + return $self; + } + + public function withXSentAt(mixed $xSentAt): self + { + $self = clone $this; + $self['xSentAt'] = $xSentAt; + + return $self; + } + + public function withXStreamResponse(mixed $xStreamResponse): self + { + $self = clone $this; + $self['xStreamResponse'] = $xStreamResponse; + + return $self; + } +} diff --git a/src/Sessions/SessionEndParams.php b/src/Sessions/SessionEndParams.php new file mode 100644 index 0000000..7c40b6d --- /dev/null +++ b/src/Sessions/SessionEndParams.php @@ -0,0 +1,99 @@ + */ + use SdkModel; + use SdkParams; + + #[Optional] + public mixed $xLanguage; + + #[Optional] + public mixed $xSDKVersion; + + #[Optional] + public mixed $xSentAt; + + #[Optional] + public mixed $xStreamResponse; + + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with( + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, + ): self { + $self = new self; + + null !== $xLanguage && $self['xLanguage'] = $xLanguage; + null !== $xSDKVersion && $self['xSDKVersion'] = $xSDKVersion; + null !== $xSentAt && $self['xSentAt'] = $xSentAt; + null !== $xStreamResponse && $self['xStreamResponse'] = $xStreamResponse; + + return $self; + } + + public function withXLanguage(mixed $xLanguage): self + { + $self = clone $this; + $self['xLanguage'] = $xLanguage; + + return $self; + } + + public function withXSDKVersion(mixed $xSDKVersion): self + { + $self = clone $this; + $self['xSDKVersion'] = $xSDKVersion; + + return $self; + } + + public function withXSentAt(mixed $xSentAt): self + { + $self = clone $this; + $self['xSentAt'] = $xSentAt; + + return $self; + } + + public function withXStreamResponse(mixed $xStreamResponse): self + { + $self = clone $this; + $self['xStreamResponse'] = $xStreamResponse; + + return $self; + } +} diff --git a/src/Sessions/SessionExecuteAgentParams.php b/src/Sessions/SessionExecuteAgentParams.php new file mode 100644 index 0000000..379e90a --- /dev/null +++ b/src/Sessions/SessionExecuteAgentParams.php @@ -0,0 +1,113 @@ + */ + use SdkModel; + use SdkParams; + + #[Optional] + public mixed $body; + + #[Optional] + public mixed $xLanguage; + + #[Optional] + public mixed $xSDKVersion; + + #[Optional] + public mixed $xSentAt; + + #[Optional] + public mixed $xStreamResponse; + + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with( + mixed $body = null, + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, + ): self { + $self = new self; + + null !== $body && $self['body'] = $body; + null !== $xLanguage && $self['xLanguage'] = $xLanguage; + null !== $xSDKVersion && $self['xSDKVersion'] = $xSDKVersion; + null !== $xSentAt && $self['xSentAt'] = $xSentAt; + null !== $xStreamResponse && $self['xStreamResponse'] = $xStreamResponse; + + return $self; + } + + public function withBody(mixed $body): self + { + $self = clone $this; + $self['body'] = $body; + + return $self; + } + + public function withXLanguage(mixed $xLanguage): self + { + $self = clone $this; + $self['xLanguage'] = $xLanguage; + + return $self; + } + + public function withXSDKVersion(mixed $xSDKVersion): self + { + $self = clone $this; + $self['xSDKVersion'] = $xSDKVersion; + + return $self; + } + + public function withXSentAt(mixed $xSentAt): self + { + $self = clone $this; + $self['xSentAt'] = $xSentAt; + + return $self; + } + + public function withXStreamResponse(mixed $xStreamResponse): self + { + $self = clone $this; + $self['xStreamResponse'] = $xStreamResponse; + + return $self; + } +} diff --git a/src/Sessions/SessionExtractParams.php b/src/Sessions/SessionExtractParams.php new file mode 100644 index 0000000..84f4b5c --- /dev/null +++ b/src/Sessions/SessionExtractParams.php @@ -0,0 +1,113 @@ + */ + use SdkModel; + use SdkParams; + + #[Optional] + public mixed $body; + + #[Optional] + public mixed $xLanguage; + + #[Optional] + public mixed $xSDKVersion; + + #[Optional] + public mixed $xSentAt; + + #[Optional] + public mixed $xStreamResponse; + + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with( + mixed $body = null, + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, + ): self { + $self = new self; + + null !== $body && $self['body'] = $body; + null !== $xLanguage && $self['xLanguage'] = $xLanguage; + null !== $xSDKVersion && $self['xSDKVersion'] = $xSDKVersion; + null !== $xSentAt && $self['xSentAt'] = $xSentAt; + null !== $xStreamResponse && $self['xStreamResponse'] = $xStreamResponse; + + return $self; + } + + public function withBody(mixed $body): self + { + $self = clone $this; + $self['body'] = $body; + + return $self; + } + + public function withXLanguage(mixed $xLanguage): self + { + $self = clone $this; + $self['xLanguage'] = $xLanguage; + + return $self; + } + + public function withXSDKVersion(mixed $xSDKVersion): self + { + $self = clone $this; + $self['xSDKVersion'] = $xSDKVersion; + + return $self; + } + + public function withXSentAt(mixed $xSentAt): self + { + $self = clone $this; + $self['xSentAt'] = $xSentAt; + + return $self; + } + + public function withXStreamResponse(mixed $xStreamResponse): self + { + $self = clone $this; + $self['xStreamResponse'] = $xStreamResponse; + + return $self; + } +} diff --git a/src/Sessions/SessionNavigateParams.php b/src/Sessions/SessionNavigateParams.php new file mode 100644 index 0000000..0bf0197 --- /dev/null +++ b/src/Sessions/SessionNavigateParams.php @@ -0,0 +1,113 @@ + */ + use SdkModel; + use SdkParams; + + #[Optional] + public mixed $body; + + #[Optional] + public mixed $xLanguage; + + #[Optional] + public mixed $xSDKVersion; + + #[Optional] + public mixed $xSentAt; + + #[Optional] + public mixed $xStreamResponse; + + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with( + mixed $body = null, + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, + ): self { + $self = new self; + + null !== $body && $self['body'] = $body; + null !== $xLanguage && $self['xLanguage'] = $xLanguage; + null !== $xSDKVersion && $self['xSDKVersion'] = $xSDKVersion; + null !== $xSentAt && $self['xSentAt'] = $xSentAt; + null !== $xStreamResponse && $self['xStreamResponse'] = $xStreamResponse; + + return $self; + } + + public function withBody(mixed $body): self + { + $self = clone $this; + $self['body'] = $body; + + return $self; + } + + public function withXLanguage(mixed $xLanguage): self + { + $self = clone $this; + $self['xLanguage'] = $xLanguage; + + return $self; + } + + public function withXSDKVersion(mixed $xSDKVersion): self + { + $self = clone $this; + $self['xSDKVersion'] = $xSDKVersion; + + return $self; + } + + public function withXSentAt(mixed $xSentAt): self + { + $self = clone $this; + $self['xSentAt'] = $xSentAt; + + return $self; + } + + public function withXStreamResponse(mixed $xStreamResponse): self + { + $self = clone $this; + $self['xStreamResponse'] = $xStreamResponse; + + return $self; + } +} diff --git a/src/Sessions/SessionObserveParams.php b/src/Sessions/SessionObserveParams.php new file mode 100644 index 0000000..6f432c2 --- /dev/null +++ b/src/Sessions/SessionObserveParams.php @@ -0,0 +1,113 @@ + */ + use SdkModel; + use SdkParams; + + #[Optional] + public mixed $body; + + #[Optional] + public mixed $xLanguage; + + #[Optional] + public mixed $xSDKVersion; + + #[Optional] + public mixed $xSentAt; + + #[Optional] + public mixed $xStreamResponse; + + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with( + mixed $body = null, + mixed $xLanguage = null, + mixed $xSDKVersion = null, + mixed $xSentAt = null, + mixed $xStreamResponse = null, + ): self { + $self = new self; + + null !== $body && $self['body'] = $body; + null !== $xLanguage && $self['xLanguage'] = $xLanguage; + null !== $xSDKVersion && $self['xSDKVersion'] = $xSDKVersion; + null !== $xSentAt && $self['xSentAt'] = $xSentAt; + null !== $xStreamResponse && $self['xStreamResponse'] = $xStreamResponse; + + return $self; + } + + public function withBody(mixed $body): self + { + $self = clone $this; + $self['body'] = $body; + + return $self; + } + + public function withXLanguage(mixed $xLanguage): self + { + $self = clone $this; + $self['xLanguage'] = $xLanguage; + + return $self; + } + + public function withXSDKVersion(mixed $xSDKVersion): self + { + $self = clone $this; + $self['xSDKVersion'] = $xSDKVersion; + + return $self; + } + + public function withXSentAt(mixed $xSentAt): self + { + $self = clone $this; + $self['xSentAt'] = $xSentAt; + + return $self; + } + + public function withXStreamResponse(mixed $xStreamResponse): self + { + $self = clone $this; + $self['xStreamResponse'] = $xStreamResponse; + + return $self; + } +} diff --git a/tests/Services/SessionsTest.php b/tests/Services/SessionsTest.php index af48882..4fb48eb 100644 --- a/tests/Services/SessionsTest.php +++ b/tests/Services/SessionsTest.php @@ -31,6 +31,84 @@ protected function setUp(): void $this->client = $client; } + #[Test] + public function testAct(): void + { + if (UnsupportedMockTests::$skip) { + $this->markTestSkipped('Prism tests are disabled'); + } + + $result = $this->client->sessions->act((object) []); + + // @phpstan-ignore-next-line method.alreadyNarrowedType + $this->assertIsNotResource($result); + } + + #[Test] + public function testEnd(): void + { + if (UnsupportedMockTests::$skip) { + $this->markTestSkipped('Prism tests are disabled'); + } + + $result = $this->client->sessions->end((object) []); + + // @phpstan-ignore-next-line method.alreadyNarrowedType + $this->assertIsNotResource($result); + } + + #[Test] + public function testExecuteAgent(): void + { + if (UnsupportedMockTests::$skip) { + $this->markTestSkipped('Prism tests are disabled'); + } + + $result = $this->client->sessions->executeAgent((object) []); + + // @phpstan-ignore-next-line method.alreadyNarrowedType + $this->assertIsNotResource($result); + } + + #[Test] + public function testExtract(): void + { + if (UnsupportedMockTests::$skip) { + $this->markTestSkipped('Prism tests are disabled'); + } + + $result = $this->client->sessions->extract((object) []); + + // @phpstan-ignore-next-line method.alreadyNarrowedType + $this->assertIsNotResource($result); + } + + #[Test] + public function testNavigate(): void + { + if (UnsupportedMockTests::$skip) { + $this->markTestSkipped('Prism tests are disabled'); + } + + $result = $this->client->sessions->navigate((object) []); + + // @phpstan-ignore-next-line method.alreadyNarrowedType + $this->assertIsNotResource($result); + } + + #[Test] + public function testObserve(): void + { + if (UnsupportedMockTests::$skip) { + $this->markTestSkipped('Prism tests are disabled'); + } + + $result = $this->client->sessions->observe((object) []); + + // @phpstan-ignore-next-line method.alreadyNarrowedType + $this->assertIsNotResource($result); + } + #[Test] public function testStart(): void { From 7a4328bfa32b6475cb2cbf1da56cb9d2d1fef514 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 05:28:05 +0000 Subject: [PATCH 04/29] feat!: use aliases for phpstan types --- src/Core/Concerns/SdkModel.php | 2 -- src/ServiceContracts/SessionsRawContract.php | 14 +++++++------- src/Sessions/ModelConfig.php | 5 +++++ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Core/Concerns/SdkModel.php b/src/Core/Concerns/SdkModel.php index 96f7f65..dc02763 100644 --- a/src/Core/Concerns/SdkModel.php +++ b/src/Core/Concerns/SdkModel.php @@ -75,8 +75,6 @@ public function __toString(): string * a native class property, indicating an omitted value, * or a property overridden with an incongruent type * - * @return value-of - * * @throws \Exception */ public function __get(string $key): mixed diff --git a/src/ServiceContracts/SessionsRawContract.php b/src/ServiceContracts/SessionsRawContract.php index defe127..2fb0524 100644 --- a/src/ServiceContracts/SessionsRawContract.php +++ b/src/ServiceContracts/SessionsRawContract.php @@ -21,7 +21,7 @@ interface SessionsRawContract * @api * * @param mixed $id Path param: Unique session identifier - * @param array|SessionActParams $params + * @param array|SessionActParams $params * * @return BaseResponse * @@ -37,7 +37,7 @@ public function act( * @api * * @param mixed $id Unique session identifier - * @param array|SessionEndParams $params + * @param array|SessionEndParams $params * * @return BaseResponse * @@ -53,7 +53,7 @@ public function end( * @api * * @param mixed $id Path param: Unique session identifier - * @param array|SessionExecuteAgentParams $params + * @param array|SessionExecuteAgentParams $params * * @return BaseResponse * @@ -69,7 +69,7 @@ public function executeAgent( * @api * * @param mixed $id Path param: Unique session identifier - * @param array|SessionExtractParams $params + * @param array|SessionExtractParams $params * * @return BaseResponse * @@ -85,7 +85,7 @@ public function extract( * @api * * @param mixed $id Path param: Unique session identifier - * @param array|SessionNavigateParams $params + * @param array|SessionNavigateParams $params * * @return BaseResponse * @@ -101,7 +101,7 @@ public function navigate( * @api * * @param mixed $id Path param: Unique session identifier - * @param array|SessionObserveParams $params + * @param array|SessionObserveParams $params * * @return BaseResponse * @@ -116,7 +116,7 @@ public function observe( /** * @api * - * @param array|SessionStartParams $params + * @param array|SessionStartParams $params * * @return BaseResponse * diff --git a/src/Sessions/ModelConfig.php b/src/Sessions/ModelConfig.php index 47c97ad..af40bc4 100644 --- a/src/Sessions/ModelConfig.php +++ b/src/Sessions/ModelConfig.php @@ -9,6 +9,11 @@ use Stagehand\Core\Conversion\Contracts\ConverterSource; use Stagehand\Sessions\ModelConfig\UnionMember1; +/** + * @phpstan-import-type UnionMember1Shape from \Stagehand\Sessions\ModelConfig\UnionMember1 + * + * @phpstan-type ModelConfigShape = string|UnionMember1Shape + */ final class ModelConfig implements ConverterSource { use SdkUnion; From 4b195d7ecfae72625b33ce440cd9bb83aa6deeea Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 05:29:59 +0000 Subject: [PATCH 05/29] fix: support arrays in query param construction --- src/Core/Util.php | 35 ++++++++++++++---------- tests/Core/ModelTest.php | 59 ++++++++-------------------------------- tests/Core/UtilTest.php | 57 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 85 insertions(+), 66 deletions(-) diff --git a/src/Core/Util.php b/src/Core/Util.php index f70edca..ccc5941 100644 --- a/src/Core/Util.php +++ b/src/Core/Util.php @@ -87,6 +87,20 @@ public static function array_filter_omit(array $arr): array return array_filter($arr, fn ($v, $_) => OMIT !== $v, mode: ARRAY_FILTER_USE_BOTH); } + public static function strVal(mixed $value): string + { + if (is_bool($value)) { + return $value ? 'true' : 'false'; + } + + if (is_object($value) && is_a($value, class: \DateTimeInterface::class)) { + return date_format($value, format: \DateTimeInterface::RFC3339); + } + + // @phpstan-ignore-next-line argument.type + return strval($value); + } + /** * @param callable $callback */ @@ -185,7 +199,12 @@ public static function joinUri( parse_str($parsed['query'] ?? '', $q2); $mergedQuery = array_merge_recursive($q1, $q2, $query); - $normalizedQuery = array_map(static fn ($v) => self::strVal($v), array: $mergedQuery); + + /** @var array */ + $normalizedQuery = self::mapRecursive( + static fn ($v) => is_bool($v) || is_numeric($v) ? self::strVal($v) : $v, + value: $mergedQuery + ); $qs = http_build_query($normalizedQuery, encoding_type: PHP_QUERY_RFC3986); return $base->withQuery($qs); @@ -409,20 +428,6 @@ public static function prettyEncodeJson(mixed $obj): string return json_encode($obj, flags: JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) ?: ''; } - private static function strVal(mixed $value): string - { - if (is_bool($value)) { - return $value ? 'true' : 'false'; - } - - if (is_object($value) && is_a($value, class: \DateTimeInterface::class)) { - return date_format($value, format: \DateTimeInterface::RFC3339); - } - - // @phpstan-ignore-next-line argument.type - return strval($value); - } - /** * @param list $closing * diff --git a/tests/Core/ModelTest.php b/tests/Core/ModelTest.php index 0262592..8d3d680 100644 --- a/tests/Core/ModelTest.php +++ b/tests/Core/ModelTest.php @@ -10,7 +10,7 @@ use Stagehand\Core\Concerns\SdkModel; use Stagehand\Core\Contracts\BaseModel; -class Model implements BaseModel +class Dog implements BaseModel { /** @use SdkModel> */ use SdkModel; @@ -43,7 +43,7 @@ public function __construct( $this->ageYears = $ageYears; $this->owner = $owner; - null != $friends && $this->friends = $friends; + null !== $friends && $this['friends'] = $friends; } } @@ -58,11 +58,7 @@ class ModelTest extends TestCase #[Test] public function testBasicGetAndSet(): void { - $model = new Model( - name: 'Bob', - ageYears: 12, - owner: null, - ); + $model = new Dog(name: 'Bob', ageYears: 12, owner: null); $this->assertEquals(12, $model->ageYears); ++$model->ageYears; @@ -72,11 +68,7 @@ public function testBasicGetAndSet(): void #[Test] public function testNullAccess(): void { - $model = new Model( - name: 'Bob', - ageYears: 12, - owner: null, - ); + $model = new Dog(name: 'Bob', ageYears: 12, owner: null); $this->assertNull($model->owner); $this->assertNull($model->friends); } @@ -84,11 +76,7 @@ public function testNullAccess(): void #[Test] public function testArrayGetAndSet(): void { - $model = new Model( - name: 'Bob', - ageYears: 12, - owner: null, - ); + $model = new Dog(name: 'Bob', ageYears: 12, owner: null); $model->friends ??= []; $this->assertEquals([], $model->friends); $model->friends[] = 'Alice'; @@ -98,16 +86,8 @@ public function testArrayGetAndSet(): void #[Test] public function testDiscernsBetweenNullAndUnset(): void { - $modelUnsetFriends = new Model( - name: 'Bob', - ageYears: 12, - owner: null, - ); - $modelNullFriends = new Model( - name: 'bob', - ageYears: 12, - owner: null, - ); + $modelUnsetFriends = new Dog(name: 'Bob', ageYears: 12, owner: null); + $modelNullFriends = new Dog(name: 'bob', ageYears: 12, owner: null); $modelNullFriends->friends = null; $this->assertEquals(12, $modelUnsetFriends->ageYears); @@ -126,11 +106,7 @@ public function testDiscernsBetweenNullAndUnset(): void #[Test] public function testIssetOnOmittedProperties(): void { - $model = new Model( - name: 'Bob', - ageYears: 12, - owner: null, - ); + $model = new Dog(name: 'Bob', ageYears: 12, owner: null); $this->assertFalse(isset($model->owner)); $this->assertFalse(isset($model->friends)); } @@ -138,12 +114,7 @@ public function testIssetOnOmittedProperties(): void #[Test] public function testSerializeBasicModel(): void { - $model = new Model( - name: 'Bob', - ageYears: 12, - owner: 'Eve', - friends: ['Alice', 'Charlie'], - ); + $model = new Dog(name: 'Bob', ageYears: 12, owner: 'Eve', friends: ['Alice', 'Charlie']); $this->assertEquals( '{"name":"Bob","age_years":12,"friends":["Alice","Charlie"],"owner":"Eve"}', json_encode($model) @@ -153,11 +124,7 @@ public function testSerializeBasicModel(): void #[Test] public function testSerializeModelWithOmittedProperties(): void { - $model = new Model( - name: 'Bob', - ageYears: 12, - owner: null, - ); + $model = new Dog(name: 'Bob', ageYears: 12, owner: null); $this->assertEquals( '{"name":"Bob","age_years":12,"owner":null}', json_encode($model) @@ -167,11 +134,7 @@ public function testSerializeModelWithOmittedProperties(): void #[Test] public function testSerializeModelWithExplicitNull(): void { - $model = new Model( - name: 'Bob', - ageYears: 12, - owner: null, - ); + $model = new Dog(name: 'Bob', ageYears: 12, owner: null); $model->friends = null; $this->assertEquals( '{"name":"Bob","age_years":12,"friends":null,"owner":null}', diff --git a/tests/Core/UtilTest.php b/tests/Core/UtilTest.php index d4cd0ac..63fd6fb 100644 --- a/tests/Core/UtilTest.php +++ b/tests/Core/UtilTest.php @@ -2,6 +2,7 @@ namespace Tests\Core; +use Http\Discovery\Psr17FactoryDiscovery; use PHPUnit\Framework\Attributes\CoversNothing; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; @@ -29,11 +30,61 @@ public function testMapRecursive(): void ['b' => [null, null], 'c' => ['e' => 0], 'f' => []], static fn ($vs) => is_array($vs) && !array_is_list($vs) ? array_filter($vs, callback: static fn ($v) => !is_null($v)) : $vs, ], + [ + ['a' => null, 'b' => 2, 'c' => true, 'd' => [1, 2]], + ['a' => null, 'b' => '2', 'c' => true, 'd' => ['1', '2']], + static fn ($v) => is_bool($v) || is_numeric($v) ? Util::strVal($v) : $v, + ], + ]; + + foreach ($cases as [$input, $expected, $xform]) { + $actual = Util::mapRecursive($xform, value: $input); + $this->assertEquals($expected, $actual); + } + } + + #[Test] + public function testJoinUri(): void + { + $factory = Psr17FactoryDiscovery::findUriFactory(); + $base = $factory->createUri('http://localhost'); + $cases = [ + [ + '', + [], + 'http://localhost', + ], + [ + 'dog', + [], + 'http://localhost/dog', + ], + [ + '', + ['dog' => 'dog'], + 'http://localhost?dog=dog', + ], + [ + '', + ['dog' => ['dog']], + 'http://localhost?dog[0]=dog', + ], + [ + '', + ['dog' => [true, false]], + 'http://localhost?dog[0]=true&dog[1]=false', + ], + [ + '', + ['dog' => ['dog' => ['dog']]], + 'http://localhost?dog[dog][0]=dog', + ], ]; - foreach ($cases as [$input, $output, $xform]) { - $mapped = Util::mapRecursive($xform, value: $input); - $this->assertEquals($mapped, $output); + foreach ($cases as [$path, $query, $output]) { + $expected = $factory->createUri($output); + $actual = Util::joinUri($base, path: $path, query: $query); + $this->assertEquals($expected, $actual); } } } From 771540668a5d44d36d65b566b8c1cacfc1a0312d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 18:21:15 +0000 Subject: [PATCH 06/29] feat(api): manual updates --- .stats.yml | 6 +- README.md | 14 +- src/ServiceContracts/SessionsContract.php | 316 +++++++++++---- src/ServiceContracts/SessionsRawContract.php | 53 +-- src/Services/SessionsRawService.php | 377 ++++++++++++------ src/Services/SessionsService.php | 352 +++++++++++----- src/Sessions/SessionActParams.php | 156 ++++++-- src/Sessions/SessionActParams/Input.php | 30 ++ .../SessionActParams/Input/ActionInput.php | 141 +++++++ src/Sessions/SessionActParams/Options.php | 104 +++++ src/Sessions/SessionActParams/XLanguage.php | 17 + .../SessionActParams/XStreamResponse.php | 15 + src/Sessions/SessionActResponse.php | 84 ++++ src/Sessions/SessionActResponse/Data.php | 94 +++++ .../SessionActResponse/Data/Result.php | 144 +++++++ src/Sessions/SessionEndParams.php | 76 +++- src/Sessions/SessionEndParams/XLanguage.php | 17 + .../SessionEndParams/XStreamResponse.php | 15 + src/Sessions/SessionEndResponse.php | 62 +++ src/Sessions/SessionExecuteAgentParams.php | 113 ------ src/Sessions/SessionExecuteParams.php | 215 ++++++++++ .../SessionExecuteParams/AgentConfig.php | 97 +++++ .../SessionExecuteParams/ExecuteOptions.php | 111 ++++++ .../SessionExecuteParams/XLanguage.php | 17 + .../SessionExecuteParams/XStreamResponse.php | 15 + src/Sessions/SessionExecuteResponse.php | 84 ++++ src/Sessions/SessionExecuteResponse/Data.php | 70 ++++ .../SessionExecuteResponse/Data/Result.php | 179 +++++++++ .../Data/Result/Action.php | 183 +++++++++ .../Data/Result/Usage.php | 126 ++++++ src/Sessions/SessionExtractParams.php | 158 ++++++-- src/Sessions/SessionExtractParams/Options.php | 97 +++++ .../SessionExtractParams/XLanguage.php | 17 + .../SessionExtractParams/XStreamResponse.php | 15 + src/Sessions/SessionExtractResponse.php | 84 ++++ src/Sessions/SessionExtractResponse/Data.php | 88 ++++ src/Sessions/SessionNavigateParams.php | 151 +++++-- .../SessionNavigateParams/Options.php | 104 +++++ .../Options/WaitUntil.php | 17 + .../SessionNavigateParams/XLanguage.php | 17 + .../SessionNavigateParams/XStreamResponse.php | 15 + src/Sessions/SessionNavigateResponse.php | 84 ++++ src/Sessions/SessionNavigateResponse/Data.php | 88 ++++ src/Sessions/SessionObserveParams.php | 133 ++++-- src/Sessions/SessionObserveParams/Options.php | 97 +++++ .../SessionObserveParams/XLanguage.php | 17 + .../SessionObserveParams/XStreamResponse.php | 15 + src/Sessions/SessionObserveResponse.php | 84 ++++ src/Sessions/SessionObserveResponse/Data.php | 93 +++++ src/Sessions/SessionStartParams.php | 310 ++++++++++++-- src/Sessions/SessionStartParams/Browser.php | 105 +++++ .../Browser/LaunchOptions.php | 315 +++++++++++++++ .../LaunchOptions/IgnoreDefaultArgs.php | 26 ++ .../Browser/LaunchOptions/Proxy.php | 109 +++++ .../Browser/LaunchOptions/Viewport.php | 74 ++++ .../SessionStartParams/Browser/Type.php | 15 + .../BrowserbaseSessionCreateParams.php | 178 +++++++++ .../BrowserSettings.php | 183 +++++++++ .../BrowserSettings/Context.php | 76 ++++ .../BrowserSettings/Fingerprint.php | 158 ++++++++ .../BrowserSettings/Fingerprint/Browser.php | 16 + .../BrowserSettings/Fingerprint/Device.php | 12 + .../Fingerprint/HTTPVersion.php | 12 + .../Fingerprint/OperatingSystem.php | 18 + .../BrowserSettings/Fingerprint/Screen.php | 93 +++++ .../BrowserSettings/Viewport.php | 60 +++ .../Proxies.php | 29 ++ .../Proxies/UnionMember1.php | 30 ++ .../UnionMember1/BrowserbaseProxyConfig.php | 109 +++++ .../BrowserbaseProxyConfig/Geolocation.php | 93 +++++ .../BrowserbaseProxyConfig/Type.php | 10 + .../UnionMember1/ExternalProxyConfig.php | 130 ++++++ .../UnionMember1/ExternalProxyConfig/Type.php | 10 + .../BrowserbaseSessionCreateParams/Region.php | 16 + src/Sessions/SessionStartParams/XLanguage.php | 17 + .../SessionStartParams/XStreamResponse.php | 15 + src/Sessions/SessionStartResponse.php | 84 ++++ src/Sessions/SessionStartResponse/Data.php | 80 ++++ tests/Services/SessionsTest.php | 222 ++++++++++- 79 files changed, 6659 insertions(+), 603 deletions(-) create mode 100644 src/Sessions/SessionActParams/Input.php create mode 100644 src/Sessions/SessionActParams/Input/ActionInput.php create mode 100644 src/Sessions/SessionActParams/Options.php create mode 100644 src/Sessions/SessionActParams/XLanguage.php create mode 100644 src/Sessions/SessionActParams/XStreamResponse.php create mode 100644 src/Sessions/SessionActResponse.php create mode 100644 src/Sessions/SessionActResponse/Data.php create mode 100644 src/Sessions/SessionActResponse/Data/Result.php create mode 100644 src/Sessions/SessionEndParams/XLanguage.php create mode 100644 src/Sessions/SessionEndParams/XStreamResponse.php create mode 100644 src/Sessions/SessionEndResponse.php delete mode 100644 src/Sessions/SessionExecuteAgentParams.php create mode 100644 src/Sessions/SessionExecuteParams.php create mode 100644 src/Sessions/SessionExecuteParams/AgentConfig.php create mode 100644 src/Sessions/SessionExecuteParams/ExecuteOptions.php create mode 100644 src/Sessions/SessionExecuteParams/XLanguage.php create mode 100644 src/Sessions/SessionExecuteParams/XStreamResponse.php create mode 100644 src/Sessions/SessionExecuteResponse.php create mode 100644 src/Sessions/SessionExecuteResponse/Data.php create mode 100644 src/Sessions/SessionExecuteResponse/Data/Result.php create mode 100644 src/Sessions/SessionExecuteResponse/Data/Result/Action.php create mode 100644 src/Sessions/SessionExecuteResponse/Data/Result/Usage.php create mode 100644 src/Sessions/SessionExtractParams/Options.php create mode 100644 src/Sessions/SessionExtractParams/XLanguage.php create mode 100644 src/Sessions/SessionExtractParams/XStreamResponse.php create mode 100644 src/Sessions/SessionExtractResponse.php create mode 100644 src/Sessions/SessionExtractResponse/Data.php create mode 100644 src/Sessions/SessionNavigateParams/Options.php create mode 100644 src/Sessions/SessionNavigateParams/Options/WaitUntil.php create mode 100644 src/Sessions/SessionNavigateParams/XLanguage.php create mode 100644 src/Sessions/SessionNavigateParams/XStreamResponse.php create mode 100644 src/Sessions/SessionNavigateResponse.php create mode 100644 src/Sessions/SessionNavigateResponse/Data.php create mode 100644 src/Sessions/SessionObserveParams/Options.php create mode 100644 src/Sessions/SessionObserveParams/XLanguage.php create mode 100644 src/Sessions/SessionObserveParams/XStreamResponse.php create mode 100644 src/Sessions/SessionObserveResponse.php create mode 100644 src/Sessions/SessionObserveResponse/Data.php create mode 100644 src/Sessions/SessionStartParams/Browser.php create mode 100644 src/Sessions/SessionStartParams/Browser/LaunchOptions.php create mode 100644 src/Sessions/SessionStartParams/Browser/LaunchOptions/IgnoreDefaultArgs.php create mode 100644 src/Sessions/SessionStartParams/Browser/LaunchOptions/Proxy.php create mode 100644 src/Sessions/SessionStartParams/Browser/LaunchOptions/Viewport.php create mode 100644 src/Sessions/SessionStartParams/Browser/Type.php create mode 100644 src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams.php create mode 100644 src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings.php create mode 100644 src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Context.php create mode 100644 src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Fingerprint.php create mode 100644 src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Fingerprint/Browser.php create mode 100644 src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Fingerprint/Device.php create mode 100644 src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Fingerprint/HTTPVersion.php create mode 100644 src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Fingerprint/OperatingSystem.php create mode 100644 src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Fingerprint/Screen.php create mode 100644 src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Viewport.php create mode 100644 src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies.php create mode 100644 src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1.php create mode 100644 src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig.php create mode 100644 src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig/Geolocation.php create mode 100644 src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig/Type.php create mode 100644 src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/ExternalProxyConfig.php create mode 100644 src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/ExternalProxyConfig/Type.php create mode 100644 src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Region.php create mode 100644 src/Sessions/SessionStartParams/XLanguage.php create mode 100644 src/Sessions/SessionStartParams/XStreamResponse.php create mode 100644 src/Sessions/SessionStartResponse.php create mode 100644 src/Sessions/SessionStartResponse/Data.php diff --git a/.stats.yml b/.stats.yml index c436ede..87bd24b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-c1a6f03afe5d6823c198e5ac476fb688dacc783dae1fefdf6bf142084e298e16.yml -openapi_spec_hash: d20e8f697ce8d5bb80295fc1e8ce02e8 -config_hash: e457d704d820df5d25acfd379169f132 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-349e1b0f6291eedd731c1660155a50adcb3424fb8cd9e17bbdc0939ff3bbffcd.yml +openapi_spec_hash: 456b593ea71d72bc31a6338a25363e9f +config_hash: 5f6b5ec6e84fb01932ba87c6a9623d9b diff --git a/README.md b/README.md index 5eb55ef..165ffd6 100644 --- a/README.md +++ b/README.md @@ -55,9 +55,9 @@ $client = new Client( modelAPIKey: getenv('MODEL_API_KEY') ?: 'My Model API Key', ); -$response = $client->sessions->start(); +$response = $client->sessions->act('c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123'); -var_dump($response); +var_dump($response->data); ``` ### Value Objects @@ -77,7 +77,7 @@ When the library is unable to connect to the API, or if the API returns a non-su use Stagehand\Core\Exceptions\APIConnectionException; try { - $response = $client->sessions->start(); + $response = $client->sessions->act('c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123'); } catch (APIConnectionException $e) { echo "The server could not be reached", PHP_EOL; var_dump($e->getPrevious()); @@ -123,8 +123,9 @@ use Stagehand\RequestOptions; $client = new Client(maxRetries: 0); // Or, configure per-request: -$result = $client->sessions->start( - requestOptions: RequestOptions::with(maxRetries: 5) +$result = $client->sessions->act( + 'c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123', + requestOptions: RequestOptions::with(maxRetries: 5), ); ``` @@ -143,7 +144,8 @@ Note: the `extra*` parameters of the same name overrides the documented paramete use Stagehand\RequestOptions; -$response = $client->sessions->start( +$response = $client->sessions->act( + 'c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123', requestOptions: RequestOptions::with( extraQueryParams: ['my_query_parameter' => 'value'], extraBodyParams: ['my_body_parameter' => 'value'], diff --git a/src/ServiceContracts/SessionsContract.php b/src/ServiceContracts/SessionsContract.php index 941b801..39a68ff 100644 --- a/src/ServiceContracts/SessionsContract.php +++ b/src/ServiceContracts/SessionsContract.php @@ -6,156 +6,296 @@ use Stagehand\Core\Exceptions\APIException; use Stagehand\RequestOptions; +use Stagehand\Sessions\SessionActParams\XLanguage; +use Stagehand\Sessions\SessionActParams\XStreamResponse; +use Stagehand\Sessions\SessionActResponse; +use Stagehand\Sessions\SessionEndResponse; +use Stagehand\Sessions\SessionExecuteResponse; +use Stagehand\Sessions\SessionExtractResponse; +use Stagehand\Sessions\SessionNavigateParams\Options\WaitUntil; +use Stagehand\Sessions\SessionNavigateResponse; +use Stagehand\Sessions\SessionObserveResponse; +use Stagehand\Sessions\SessionStartParams\Browser\Type; +use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\Browser; +use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\Device; +use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\HTTPVersion; +use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\OperatingSystem; +use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Region; +use Stagehand\Sessions\SessionStartResponse; interface SessionsContract { /** * @api * - * @param mixed $id Path param: Unique session identifier - * @param mixed $body Body param: - * @param mixed $xLanguage Header param: Client SDK language - * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK - * @param mixed $xSentAt Header param: ISO timestamp when request was sent - * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * @param string $id Path param: Unique session identifier + * @param string|array{ + * description: string, + * selector: string, + * arguments?: list, + * method?: string, + * } $input Body param: Natural language instruction or Action object + * @param string $frameID Body param: Target frame ID for the action + * @param array{ + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * timeout?: float, + * variables?: array, + * } $options Body param: + * @param 'typescript'|'python'|'playground'|XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE * * @throws APIException */ public function act( - mixed $id, - mixed $body = null, - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, + string $id, + string|array $input, + ?string $frameID = null, + ?array $options = null, + string|XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|XStreamResponse|null $xStreamResponse = null, ?RequestOptions $requestOptions = null, - ): mixed; + ): SessionActResponse; /** * @api * - * @param mixed $id Unique session identifier - * @param mixed $xLanguage Client SDK language - * @param mixed $xSDKVersion Version of the Stagehand SDK - * @param mixed $xSentAt ISO timestamp when request was sent - * @param mixed $xStreamResponse Whether to stream the response via SSE + * @param string $id Unique session identifier + * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionEndParams\XLanguage $xLanguage Client SDK language + * @param string $xSDKVersion Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt ISO timestamp when request was sent + * @param 'true'|'false'|\Stagehand\Sessions\SessionEndParams\XStreamResponse $xStreamResponse Whether to stream the response via SSE * * @throws APIException */ public function end( - mixed $id, - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, + string $id, + string|\Stagehand\Sessions\SessionEndParams\XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|\Stagehand\Sessions\SessionEndParams\XStreamResponse|null $xStreamResponse = null, ?RequestOptions $requestOptions = null, - ): mixed; + ): SessionEndResponse; /** * @api * - * @param mixed $id Path param: Unique session identifier - * @param mixed $body Body param: - * @param mixed $xLanguage Header param: Client SDK language - * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK - * @param mixed $xSentAt Header param: ISO timestamp when request was sent - * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * @param string $id Path param: Unique session identifier + * @param array{ + * cua?: bool, + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * systemPrompt?: string, + * } $agentConfig Body param: + * @param array{ + * instruction: string, highlightCursor?: bool, maxSteps?: float + * } $executeOptions Body param: + * @param string $frameID Body param: Target frame ID for the agent + * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionExecuteParams\XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|\Stagehand\Sessions\SessionExecuteParams\XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE * * @throws APIException */ - public function executeAgent( - mixed $id, - mixed $body = null, - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, + public function execute( + string $id, + array $agentConfig, + array $executeOptions, + ?string $frameID = null, + string|\Stagehand\Sessions\SessionExecuteParams\XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|\Stagehand\Sessions\SessionExecuteParams\XStreamResponse|null $xStreamResponse = null, ?RequestOptions $requestOptions = null, - ): mixed; + ): SessionExecuteResponse; /** * @api * - * @param mixed $id Path param: Unique session identifier - * @param mixed $body Body param: - * @param mixed $xLanguage Header param: Client SDK language - * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK - * @param mixed $xSentAt Header param: ISO timestamp when request was sent - * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * @param string $id Path param: Unique session identifier + * @param string $frameID Body param: Target frame ID for the extraction + * @param string $instruction Body param: Natural language instruction for what to extract + * @param array{ + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * selector?: string, + * timeout?: float, + * } $options Body param: + * @param array $schema Body param: JSON Schema defining the structure of data to extract + * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionExtractParams\XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|\Stagehand\Sessions\SessionExtractParams\XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE * * @throws APIException */ public function extract( - mixed $id, - mixed $body = null, - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, + string $id, + ?string $frameID = null, + ?string $instruction = null, + ?array $options = null, + ?array $schema = null, + string|\Stagehand\Sessions\SessionExtractParams\XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|\Stagehand\Sessions\SessionExtractParams\XStreamResponse|null $xStreamResponse = null, ?RequestOptions $requestOptions = null, - ): mixed; + ): SessionExtractResponse; /** * @api * - * @param mixed $id Path param: Unique session identifier - * @param mixed $body Body param: - * @param mixed $xLanguage Header param: Client SDK language - * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK - * @param mixed $xSentAt Header param: ISO timestamp when request was sent - * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * @param string $id Path param: Unique session identifier + * @param string $url Body param: URL to navigate to + * @param string $frameID Body param: Target frame ID for the navigation + * @param array{ + * referer?: string, + * timeout?: float, + * waitUntil?: 'load'|'domcontentloaded'|'networkidle'|WaitUntil, + * } $options Body param: + * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionNavigateParams\XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|\Stagehand\Sessions\SessionNavigateParams\XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE * * @throws APIException */ public function navigate( - mixed $id, - mixed $body = null, - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, + string $id, + string $url, + ?string $frameID = null, + ?array $options = null, + string|\Stagehand\Sessions\SessionNavigateParams\XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|\Stagehand\Sessions\SessionNavigateParams\XStreamResponse|null $xStreamResponse = null, ?RequestOptions $requestOptions = null, - ): mixed; + ): SessionNavigateResponse; /** * @api * - * @param mixed $id Path param: Unique session identifier - * @param mixed $body Body param: - * @param mixed $xLanguage Header param: Client SDK language - * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK - * @param mixed $xSentAt Header param: ISO timestamp when request was sent - * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * @param string $id Path param: Unique session identifier + * @param string $frameID Body param: Target frame ID for the observation + * @param string $instruction Body param: Natural language instruction for what actions to find + * @param array{ + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * selector?: string, + * timeout?: float, + * } $options Body param: + * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionObserveParams\XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|\Stagehand\Sessions\SessionObserveParams\XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE * * @throws APIException */ public function observe( - mixed $id, - mixed $body = null, - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, + string $id, + ?string $frameID = null, + ?string $instruction = null, + ?array $options = null, + string|\Stagehand\Sessions\SessionObserveParams\XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|\Stagehand\Sessions\SessionObserveParams\XStreamResponse|null $xStreamResponse = null, ?RequestOptions $requestOptions = null, - ): mixed; + ): SessionObserveResponse; /** * @api * - * @param mixed $body Body param: - * @param mixed $xLanguage Header param: Client SDK language - * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK - * @param mixed $xSentAt Header param: ISO timestamp when request was sent - * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * @param string $modelName Body param: Model name to use for AI operations + * @param float $actTimeoutMs Body param: Timeout in ms for act operations + * @param array{ + * cdpURL?: string, + * launchOptions?: array{ + * acceptDownloads?: bool, + * args?: list, + * cdpURL?: string, + * chromiumSandbox?: bool, + * connectTimeoutMs?: float, + * deviceScaleFactor?: float, + * devtools?: bool, + * downloadsPath?: string, + * executablePath?: string, + * hasTouch?: bool, + * headless?: bool, + * ignoreDefaultArgs?: bool|list, + * ignoreHTTPSErrors?: bool, + * locale?: string, + * preserveUserDataDir?: bool, + * proxy?: array{ + * server: string, bypass?: string, password?: string, username?: string + * }, + * userDataDir?: string, + * viewport?: array{height: float, width: float}, + * }, + * type?: 'local'|'browserbase'|Type, + * } $browser Body param: + * @param array{ + * browserSettings?: array{ + * advancedStealth?: bool, + * blockAds?: bool, + * context?: array{id: string, persist?: bool}, + * extensionID?: string, + * fingerprint?: array{ + * browsers?: list<'chrome'|'edge'|'firefox'|'safari'|Browser>, + * devices?: list<'desktop'|'mobile'|Device>, + * httpVersion?: '1'|'2'|HTTPVersion, + * locales?: list, + * operatingSystems?: list<'android'|'ios'|'linux'|'macos'|'windows'|OperatingSystem>, + * screen?: array{ + * maxHeight?: float, maxWidth?: float, minHeight?: float, minWidth?: float + * }, + * }, + * logSession?: bool, + * recordSession?: bool, + * solveCaptchas?: bool, + * viewport?: array{height?: float, width?: float}, + * }, + * extensionID?: string, + * keepAlive?: bool, + * projectID?: string, + * proxies?: bool|list>, + * region?: 'us-west-2'|'us-east-1'|'eu-central-1'|'ap-southeast-1'|Region, + * timeout?: float, + * userMetadata?: array, + * } $browserbaseSessionCreateParams Body param: + * @param string $browserbaseSessionID Body param: Existing Browserbase session ID to resume + * @param bool $debugDom Body param: + * @param float $domSettleTimeoutMs Body param: Timeout in ms to wait for DOM to settle + * @param bool $experimental Body param: + * @param bool $selfHeal Body param: Enable self-healing for failed actions + * @param string $systemPrompt Body param: Custom system prompt for AI operations + * @param float $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) + * @param bool $waitForCaptchaSolves Body param: + * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionStartParams\XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|\Stagehand\Sessions\SessionStartParams\XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE * * @throws APIException */ public function start( - mixed $body = null, - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, + string $modelName, + ?float $actTimeoutMs = null, + ?array $browser = null, + ?array $browserbaseSessionCreateParams = null, + ?string $browserbaseSessionID = null, + ?bool $debugDom = null, + ?float $domSettleTimeoutMs = null, + ?bool $experimental = null, + ?bool $selfHeal = null, + ?string $systemPrompt = null, + ?float $verbose = null, + ?bool $waitForCaptchaSolves = null, + string|\Stagehand\Sessions\SessionStartParams\XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|\Stagehand\Sessions\SessionStartParams\XStreamResponse|null $xStreamResponse = null, ?RequestOptions $requestOptions = null, - ): mixed; + ): SessionStartResponse; } diff --git a/src/ServiceContracts/SessionsRawContract.php b/src/ServiceContracts/SessionsRawContract.php index 2fb0524..acc8b5f 100644 --- a/src/ServiceContracts/SessionsRawContract.php +++ b/src/ServiceContracts/SessionsRawContract.php @@ -8,27 +8,34 @@ use Stagehand\Core\Exceptions\APIException; use Stagehand\RequestOptions; use Stagehand\Sessions\SessionActParams; +use Stagehand\Sessions\SessionActResponse; use Stagehand\Sessions\SessionEndParams; -use Stagehand\Sessions\SessionExecuteAgentParams; +use Stagehand\Sessions\SessionEndResponse; +use Stagehand\Sessions\SessionExecuteParams; +use Stagehand\Sessions\SessionExecuteResponse; use Stagehand\Sessions\SessionExtractParams; +use Stagehand\Sessions\SessionExtractResponse; use Stagehand\Sessions\SessionNavigateParams; +use Stagehand\Sessions\SessionNavigateResponse; use Stagehand\Sessions\SessionObserveParams; +use Stagehand\Sessions\SessionObserveResponse; use Stagehand\Sessions\SessionStartParams; +use Stagehand\Sessions\SessionStartResponse; interface SessionsRawContract { /** * @api * - * @param mixed $id Path param: Unique session identifier + * @param string $id Path param: Unique session identifier * @param array|SessionActParams $params * - * @return BaseResponse + * @return BaseResponse * * @throws APIException */ public function act( - mixed $id, + string $id, array|SessionActParams $params, ?RequestOptions $requestOptions = null, ): BaseResponse; @@ -36,15 +43,15 @@ public function act( /** * @api * - * @param mixed $id Unique session identifier + * @param string $id Unique session identifier * @param array|SessionEndParams $params * - * @return BaseResponse + * @return BaseResponse * * @throws APIException */ public function end( - mixed $id, + string $id, array|SessionEndParams $params, ?RequestOptions $requestOptions = null, ): BaseResponse; @@ -52,31 +59,31 @@ public function end( /** * @api * - * @param mixed $id Path param: Unique session identifier - * @param array|SessionExecuteAgentParams $params + * @param string $id Path param: Unique session identifier + * @param array|SessionExecuteParams $params * - * @return BaseResponse + * @return BaseResponse * * @throws APIException */ - public function executeAgent( - mixed $id, - array|SessionExecuteAgentParams $params, + public function execute( + string $id, + array|SessionExecuteParams $params, ?RequestOptions $requestOptions = null, ): BaseResponse; /** * @api * - * @param mixed $id Path param: Unique session identifier + * @param string $id Path param: Unique session identifier * @param array|SessionExtractParams $params * - * @return BaseResponse + * @return BaseResponse * * @throws APIException */ public function extract( - mixed $id, + string $id, array|SessionExtractParams $params, ?RequestOptions $requestOptions = null, ): BaseResponse; @@ -84,15 +91,15 @@ public function extract( /** * @api * - * @param mixed $id Path param: Unique session identifier + * @param string $id Path param: Unique session identifier * @param array|SessionNavigateParams $params * - * @return BaseResponse + * @return BaseResponse * * @throws APIException */ public function navigate( - mixed $id, + string $id, array|SessionNavigateParams $params, ?RequestOptions $requestOptions = null, ): BaseResponse; @@ -100,15 +107,15 @@ public function navigate( /** * @api * - * @param mixed $id Path param: Unique session identifier + * @param string $id Path param: Unique session identifier * @param array|SessionObserveParams $params * - * @return BaseResponse + * @return BaseResponse * * @throws APIException */ public function observe( - mixed $id, + string $id, array|SessionObserveParams $params, ?RequestOptions $requestOptions = null, ): BaseResponse; @@ -118,7 +125,7 @@ public function observe( * * @param array|SessionStartParams $params * - * @return BaseResponse + * @return BaseResponse * * @throws APIException */ diff --git a/src/Services/SessionsRawService.php b/src/Services/SessionsRawService.php index 60f668d..0b6330c 100644 --- a/src/Services/SessionsRawService.php +++ b/src/Services/SessionsRawService.php @@ -11,12 +11,25 @@ use Stagehand\RequestOptions; use Stagehand\ServiceContracts\SessionsRawContract; use Stagehand\Sessions\SessionActParams; +use Stagehand\Sessions\SessionActParams\XLanguage; +use Stagehand\Sessions\SessionActParams\XStreamResponse; +use Stagehand\Sessions\SessionActResponse; use Stagehand\Sessions\SessionEndParams; -use Stagehand\Sessions\SessionExecuteAgentParams; +use Stagehand\Sessions\SessionEndResponse; +use Stagehand\Sessions\SessionExecuteParams; +use Stagehand\Sessions\SessionExecuteResponse; use Stagehand\Sessions\SessionExtractParams; +use Stagehand\Sessions\SessionExtractResponse; use Stagehand\Sessions\SessionNavigateParams; +use Stagehand\Sessions\SessionNavigateParams\Options\WaitUntil; +use Stagehand\Sessions\SessionNavigateResponse; use Stagehand\Sessions\SessionObserveParams; +use Stagehand\Sessions\SessionObserveResponse; use Stagehand\Sessions\SessionStartParams; +use Stagehand\Sessions\SessionStartParams\Browser\Type; +use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\HTTPVersion; +use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Region; +use Stagehand\Sessions\SessionStartResponse; final class SessionsRawService implements SessionsRawContract { @@ -31,21 +44,32 @@ public function __construct(private Client $client) {} * * Executes a browser action using natural language instructions or a predefined Action object. * - * @param mixed $id Path param: Unique session identifier + * @param string $id Path param: Unique session identifier * @param array{ - * body?: mixed, - * xLanguage?: mixed, - * xSDKVersion?: mixed, - * xSentAt?: mixed, - * xStreamResponse?: mixed, + * input: string|array{ + * description: string, + * selector: string, + * arguments?: list, + * method?: string, + * }, + * frameID?: string, + * options?: array{ + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * timeout?: float, + * variables?: array, + * }, + * xLanguage?: 'typescript'|'python'|'playground'|XLanguage, + * xSDKVersion?: string, + * xSentAt?: string|\DateTimeInterface, + * xStreamResponse?: 'true'|'false'|XStreamResponse, * }|SessionActParams $params * - * @return BaseResponse + * @return BaseResponse * * @throws APIException */ public function act( - mixed $id, + string $id, array|SessionActParams $params, ?RequestOptions $requestOptions = null, ): BaseResponse { @@ -53,23 +77,27 @@ public function act( $params, $requestOptions, ); + $header_params = [ + 'xLanguage' => 'x-language', + 'xSDKVersion' => 'x-sdk-version', + 'xSentAt' => 'x-sent-at', + 'xStreamResponse' => 'x-stream-response', + ]; // @phpstan-ignore-next-line return.type return $this->client->request( method: 'post', - path: ['sessions/%1$s/act', $id], + path: ['v1/sessions/%1$s/act', $id], headers: Util::array_transform_keys( - array_diff_key($parsed, array_flip(['body'])), - [ - 'xLanguage' => 'x-language', - 'xSDKVersion' => 'x-sdk-version', - 'xSentAt' => 'x-sent-at', - 'xStreamResponse' => 'x-stream-response', - ], + array_intersect_key($parsed, array_flip(array_keys($header_params))), + $header_params, + ), + body: (object) array_diff_key( + $parsed, + array_flip(array_keys($header_params)) ), - body: $parsed['body'], options: $options, - convert: 'mixed', + convert: SessionActResponse::class, ); } @@ -78,20 +106,20 @@ public function act( * * Terminates the browser session and releases all associated resources. * - * @param mixed $id Unique session identifier + * @param string $id Unique session identifier * @param array{ - * xLanguage?: mixed, - * xSDKVersion?: mixed, - * xSentAt?: mixed, - * xStreamResponse?: mixed, + * xLanguage?: 'typescript'|'python'|'playground'|SessionEndParams\XLanguage, + * xSDKVersion?: string, + * xSentAt?: string|\DateTimeInterface, + * xStreamResponse?: 'true'|'false'|SessionEndParams\XStreamResponse, * }|SessionEndParams $params * - * @return BaseResponse + * @return BaseResponse * * @throws APIException */ public function end( - mixed $id, + string $id, array|SessionEndParams $params, ?RequestOptions $requestOptions = null, ): BaseResponse { @@ -103,7 +131,7 @@ public function end( // @phpstan-ignore-next-line return.type return $this->client->request( method: 'post', - path: ['sessions/%1$s/end', $id], + path: ['v1/sessions/%1$s/end', $id], headers: Util::array_transform_keys( $parsed, [ @@ -114,7 +142,7 @@ public function end( ], ), options: $options, - convert: 'mixed', + convert: SessionEndResponse::class, ); } @@ -123,45 +151,57 @@ public function end( * * Runs an autonomous AI agent that can perform complex multi-step browser tasks. * - * @param mixed $id Path param: Unique session identifier + * @param string $id Path param: Unique session identifier * @param array{ - * body?: mixed, - * xLanguage?: mixed, - * xSDKVersion?: mixed, - * xSentAt?: mixed, - * xStreamResponse?: mixed, - * }|SessionExecuteAgentParams $params + * agentConfig: array{ + * cua?: bool, + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * systemPrompt?: string, + * }, + * executeOptions: array{ + * instruction: string, highlightCursor?: bool, maxSteps?: float + * }, + * frameID?: string, + * xLanguage?: 'typescript'|'python'|'playground'|SessionExecuteParams\XLanguage, + * xSDKVersion?: string, + * xSentAt?: string|\DateTimeInterface, + * xStreamResponse?: 'true'|'false'|SessionExecuteParams\XStreamResponse, + * }|SessionExecuteParams $params * - * @return BaseResponse + * @return BaseResponse * * @throws APIException */ - public function executeAgent( - mixed $id, - array|SessionExecuteAgentParams $params, + public function execute( + string $id, + array|SessionExecuteParams $params, ?RequestOptions $requestOptions = null, ): BaseResponse { - [$parsed, $options] = SessionExecuteAgentParams::parseRequest( + [$parsed, $options] = SessionExecuteParams::parseRequest( $params, $requestOptions, ); + $header_params = [ + 'xLanguage' => 'x-language', + 'xSDKVersion' => 'x-sdk-version', + 'xSentAt' => 'x-sent-at', + 'xStreamResponse' => 'x-stream-response', + ]; // @phpstan-ignore-next-line return.type return $this->client->request( method: 'post', - path: ['sessions/%1$s/agentExecute', $id], + path: ['v1/sessions/%1$s/agentExecute', $id], headers: Util::array_transform_keys( - array_diff_key($parsed, array_flip(['body'])), - [ - 'xLanguage' => 'x-language', - 'xSDKVersion' => 'x-sdk-version', - 'xSentAt' => 'x-sent-at', - 'xStreamResponse' => 'x-stream-response', - ], + array_intersect_key($parsed, array_flip(array_keys($header_params))), + $header_params, + ), + body: (object) array_diff_key( + $parsed, + array_flip(array_keys($header_params)) ), - body: $parsed['body'], options: $options, - convert: 'mixed', + convert: SessionExecuteResponse::class, ); } @@ -170,21 +210,28 @@ public function executeAgent( * * Extracts structured data from the current page using AI-powered analysis. * - * @param mixed $id Path param: Unique session identifier + * @param string $id Path param: Unique session identifier * @param array{ - * body?: mixed, - * xLanguage?: mixed, - * xSDKVersion?: mixed, - * xSentAt?: mixed, - * xStreamResponse?: mixed, + * frameID?: string, + * instruction?: string, + * options?: array{ + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * selector?: string, + * timeout?: float, + * }, + * schema?: array, + * xLanguage?: 'typescript'|'python'|'playground'|SessionExtractParams\XLanguage, + * xSDKVersion?: string, + * xSentAt?: string|\DateTimeInterface, + * xStreamResponse?: 'true'|'false'|SessionExtractParams\XStreamResponse, * }|SessionExtractParams $params * - * @return BaseResponse + * @return BaseResponse * * @throws APIException */ public function extract( - mixed $id, + string $id, array|SessionExtractParams $params, ?RequestOptions $requestOptions = null, ): BaseResponse { @@ -192,23 +239,27 @@ public function extract( $params, $requestOptions, ); + $header_params = [ + 'xLanguage' => 'x-language', + 'xSDKVersion' => 'x-sdk-version', + 'xSentAt' => 'x-sent-at', + 'xStreamResponse' => 'x-stream-response', + ]; // @phpstan-ignore-next-line return.type return $this->client->request( method: 'post', - path: ['sessions/%1$s/extract', $id], + path: ['v1/sessions/%1$s/extract', $id], headers: Util::array_transform_keys( - array_diff_key($parsed, array_flip(['body'])), - [ - 'xLanguage' => 'x-language', - 'xSDKVersion' => 'x-sdk-version', - 'xSentAt' => 'x-sent-at', - 'xStreamResponse' => 'x-stream-response', - ], + array_intersect_key($parsed, array_flip(array_keys($header_params))), + $header_params, + ), + body: (object) array_diff_key( + $parsed, + array_flip(array_keys($header_params)) ), - body: $parsed['body'], options: $options, - convert: 'mixed', + convert: SessionExtractResponse::class, ); } @@ -217,21 +268,27 @@ public function extract( * * Navigates the browser to the specified URL. * - * @param mixed $id Path param: Unique session identifier + * @param string $id Path param: Unique session identifier * @param array{ - * body?: mixed, - * xLanguage?: mixed, - * xSDKVersion?: mixed, - * xSentAt?: mixed, - * xStreamResponse?: mixed, + * url: string, + * frameID?: string, + * options?: array{ + * referer?: string, + * timeout?: float, + * waitUntil?: 'load'|'domcontentloaded'|'networkidle'|WaitUntil, + * }, + * xLanguage?: 'typescript'|'python'|'playground'|SessionNavigateParams\XLanguage, + * xSDKVersion?: string, + * xSentAt?: string|\DateTimeInterface, + * xStreamResponse?: 'true'|'false'|SessionNavigateParams\XStreamResponse, * }|SessionNavigateParams $params * - * @return BaseResponse + * @return BaseResponse * * @throws APIException */ public function navigate( - mixed $id, + string $id, array|SessionNavigateParams $params, ?RequestOptions $requestOptions = null, ): BaseResponse { @@ -239,23 +296,27 @@ public function navigate( $params, $requestOptions, ); + $header_params = [ + 'xLanguage' => 'x-language', + 'xSDKVersion' => 'x-sdk-version', + 'xSentAt' => 'x-sent-at', + 'xStreamResponse' => 'x-stream-response', + ]; // @phpstan-ignore-next-line return.type return $this->client->request( method: 'post', - path: ['sessions/%1$s/navigate', $id], + path: ['v1/sessions/%1$s/navigate', $id], headers: Util::array_transform_keys( - array_diff_key($parsed, array_flip(['body'])), - [ - 'xLanguage' => 'x-language', - 'xSDKVersion' => 'x-sdk-version', - 'xSentAt' => 'x-sent-at', - 'xStreamResponse' => 'x-stream-response', - ], + array_intersect_key($parsed, array_flip(array_keys($header_params))), + $header_params, + ), + body: (object) array_diff_key( + $parsed, + array_flip(array_keys($header_params)) ), - body: $parsed['body'], options: $options, - convert: 'mixed', + convert: SessionNavigateResponse::class, ); } @@ -264,21 +325,27 @@ public function navigate( * * Identifies and returns available actions on the current page that match the given instruction. * - * @param mixed $id Path param: Unique session identifier + * @param string $id Path param: Unique session identifier * @param array{ - * body?: mixed, - * xLanguage?: mixed, - * xSDKVersion?: mixed, - * xSentAt?: mixed, - * xStreamResponse?: mixed, + * frameID?: string, + * instruction?: string, + * options?: array{ + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * selector?: string, + * timeout?: float, + * }, + * xLanguage?: 'typescript'|'python'|'playground'|SessionObserveParams\XLanguage, + * xSDKVersion?: string, + * xSentAt?: string|\DateTimeInterface, + * xStreamResponse?: 'true'|'false'|SessionObserveParams\XStreamResponse, * }|SessionObserveParams $params * - * @return BaseResponse + * @return BaseResponse * * @throws APIException */ public function observe( - mixed $id, + string $id, array|SessionObserveParams $params, ?RequestOptions $requestOptions = null, ): BaseResponse { @@ -286,23 +353,27 @@ public function observe( $params, $requestOptions, ); + $header_params = [ + 'xLanguage' => 'x-language', + 'xSDKVersion' => 'x-sdk-version', + 'xSentAt' => 'x-sent-at', + 'xStreamResponse' => 'x-stream-response', + ]; // @phpstan-ignore-next-line return.type return $this->client->request( method: 'post', - path: ['sessions/%1$s/observe', $id], + path: ['v1/sessions/%1$s/observe', $id], headers: Util::array_transform_keys( - array_diff_key($parsed, array_flip(['body'])), - [ - 'xLanguage' => 'x-language', - 'xSDKVersion' => 'x-sdk-version', - 'xSentAt' => 'x-sent-at', - 'xStreamResponse' => 'x-stream-response', - ], + array_intersect_key($parsed, array_flip(array_keys($header_params))), + $header_params, + ), + body: (object) array_diff_key( + $parsed, + array_flip(array_keys($header_params)) ), - body: $parsed['body'], options: $options, - convert: 'mixed', + convert: SessionObserveResponse::class, ); } @@ -312,14 +383,76 @@ public function observe( * Creates a new browser session with the specified configuration. Returns a session ID used for all subsequent operations. * * @param array{ - * body?: mixed, - * xLanguage?: mixed, - * xSDKVersion?: mixed, - * xSentAt?: mixed, - * xStreamResponse?: mixed, + * modelName: string, + * actTimeoutMs?: float, + * browser?: array{ + * cdpURL?: string, + * launchOptions?: array{ + * acceptDownloads?: bool, + * args?: list, + * cdpURL?: string, + * chromiumSandbox?: bool, + * connectTimeoutMs?: float, + * deviceScaleFactor?: float, + * devtools?: bool, + * downloadsPath?: string, + * executablePath?: string, + * hasTouch?: bool, + * headless?: bool, + * ignoreDefaultArgs?: bool|list, + * ignoreHTTPSErrors?: bool, + * locale?: string, + * preserveUserDataDir?: bool, + * proxy?: array{ + * server: string, bypass?: string, password?: string, username?: string + * }, + * userDataDir?: string, + * viewport?: array{height: float, width: float}, + * }, + * type?: 'local'|'browserbase'|Type, + * }, + * browserbaseSessionCreateParams?: array{ + * browserSettings?: array{ + * advancedStealth?: bool, + * blockAds?: bool, + * context?: array{id: string, persist?: bool}, + * extensionID?: string, + * fingerprint?: array{ + * browsers?: list, + * devices?: list, + * httpVersion?: '1'|'2'|HTTPVersion, + * locales?: list, + * operatingSystems?: list, + * screen?: array, + * }, + * logSession?: bool, + * recordSession?: bool, + * solveCaptchas?: bool, + * viewport?: array{height?: float, width?: float}, + * }, + * extensionID?: string, + * keepAlive?: bool, + * projectID?: string, + * proxies?: bool|list>, + * region?: 'us-west-2'|'us-east-1'|'eu-central-1'|'ap-southeast-1'|Region, + * timeout?: float, + * userMetadata?: array, + * }, + * browserbaseSessionID?: string, + * debugDom?: bool, + * domSettleTimeoutMs?: float, + * experimental?: bool, + * selfHeal?: bool, + * systemPrompt?: string, + * verbose?: float, + * waitForCaptchaSolves?: bool, + * xLanguage?: 'typescript'|'python'|'playground'|SessionStartParams\XLanguage, + * xSDKVersion?: string, + * xSentAt?: string|\DateTimeInterface, + * xStreamResponse?: 'true'|'false'|SessionStartParams\XStreamResponse, * }|SessionStartParams $params * - * @return BaseResponse + * @return BaseResponse * * @throws APIException */ @@ -331,23 +464,27 @@ public function start( $params, $requestOptions, ); + $header_params = [ + 'xLanguage' => 'x-language', + 'xSDKVersion' => 'x-sdk-version', + 'xSentAt' => 'x-sent-at', + 'xStreamResponse' => 'x-stream-response', + ]; // @phpstan-ignore-next-line return.type return $this->client->request( method: 'post', - path: 'sessions/start', + path: 'v1/sessions/start', headers: Util::array_transform_keys( - array_diff_key($parsed, array_flip(['body'])), - [ - 'xLanguage' => 'x-language', - 'xSDKVersion' => 'x-sdk-version', - 'xSentAt' => 'x-sent-at', - 'xStreamResponse' => 'x-stream-response', - ], + array_intersect_key($parsed, array_flip(array_keys($header_params))), + $header_params, + ), + body: (object) array_diff_key( + $parsed, + array_flip(array_keys($header_params)) ), - body: $parsed['body'], options: $options, - convert: 'mixed', + convert: SessionStartResponse::class, ); } } diff --git a/src/Services/SessionsService.php b/src/Services/SessionsService.php index 68f73c7..e35637e 100644 --- a/src/Services/SessionsService.php +++ b/src/Services/SessionsService.php @@ -9,6 +9,22 @@ use Stagehand\Core\Util; use Stagehand\RequestOptions; use Stagehand\ServiceContracts\SessionsContract; +use Stagehand\Sessions\SessionActParams\XLanguage; +use Stagehand\Sessions\SessionActParams\XStreamResponse; +use Stagehand\Sessions\SessionActResponse; +use Stagehand\Sessions\SessionEndResponse; +use Stagehand\Sessions\SessionExecuteResponse; +use Stagehand\Sessions\SessionExtractResponse; +use Stagehand\Sessions\SessionNavigateParams\Options\WaitUntil; +use Stagehand\Sessions\SessionNavigateResponse; +use Stagehand\Sessions\SessionObserveResponse; +use Stagehand\Sessions\SessionStartParams\Browser\Type; +use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\Browser; +use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\Device; +use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\HTTPVersion; +use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\OperatingSystem; +use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Region; +use Stagehand\Sessions\SessionStartResponse; final class SessionsService implements SessionsContract { @@ -30,27 +46,42 @@ public function __construct(private Client $client) * * Executes a browser action using natural language instructions or a predefined Action object. * - * @param mixed $id Path param: Unique session identifier - * @param mixed $body Body param: - * @param mixed $xLanguage Header param: Client SDK language - * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK - * @param mixed $xSentAt Header param: ISO timestamp when request was sent - * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * @param string $id Path param: Unique session identifier + * @param string|array{ + * description: string, + * selector: string, + * arguments?: list, + * method?: string, + * } $input Body param: Natural language instruction or Action object + * @param string $frameID Body param: Target frame ID for the action + * @param array{ + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * timeout?: float, + * variables?: array, + * } $options Body param: + * @param 'typescript'|'python'|'playground'|XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE * * @throws APIException */ public function act( - mixed $id, - mixed $body = null, - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, + string $id, + string|array $input, + ?string $frameID = null, + ?array $options = null, + string|XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|XStreamResponse|null $xStreamResponse = null, ?RequestOptions $requestOptions = null, - ): mixed { + ): SessionActResponse { $params = Util::removeNulls( [ - 'body' => $body, + 'input' => $input, + 'frameID' => $frameID, + 'options' => $options, 'xLanguage' => $xLanguage, 'xSDKVersion' => $xSDKVersion, 'xSentAt' => $xSentAt, @@ -69,22 +100,22 @@ public function act( * * Terminates the browser session and releases all associated resources. * - * @param mixed $id Unique session identifier - * @param mixed $xLanguage Client SDK language - * @param mixed $xSDKVersion Version of the Stagehand SDK - * @param mixed $xSentAt ISO timestamp when request was sent - * @param mixed $xStreamResponse Whether to stream the response via SSE + * @param string $id Unique session identifier + * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionEndParams\XLanguage $xLanguage Client SDK language + * @param string $xSDKVersion Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt ISO timestamp when request was sent + * @param 'true'|'false'|\Stagehand\Sessions\SessionEndParams\XStreamResponse $xStreamResponse Whether to stream the response via SSE * * @throws APIException */ public function end( - mixed $id, - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, + string $id, + string|\Stagehand\Sessions\SessionEndParams\XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|\Stagehand\Sessions\SessionEndParams\XStreamResponse|null $xStreamResponse = null, ?RequestOptions $requestOptions = null, - ): mixed { + ): SessionEndResponse { $params = Util::removeNulls( [ 'xLanguage' => $xLanguage, @@ -105,27 +136,39 @@ public function end( * * Runs an autonomous AI agent that can perform complex multi-step browser tasks. * - * @param mixed $id Path param: Unique session identifier - * @param mixed $body Body param: - * @param mixed $xLanguage Header param: Client SDK language - * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK - * @param mixed $xSentAt Header param: ISO timestamp when request was sent - * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * @param string $id Path param: Unique session identifier + * @param array{ + * cua?: bool, + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * systemPrompt?: string, + * } $agentConfig Body param: + * @param array{ + * instruction: string, highlightCursor?: bool, maxSteps?: float + * } $executeOptions Body param: + * @param string $frameID Body param: Target frame ID for the agent + * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionExecuteParams\XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|\Stagehand\Sessions\SessionExecuteParams\XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE * * @throws APIException */ - public function executeAgent( - mixed $id, - mixed $body = null, - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, + public function execute( + string $id, + array $agentConfig, + array $executeOptions, + ?string $frameID = null, + string|\Stagehand\Sessions\SessionExecuteParams\XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|\Stagehand\Sessions\SessionExecuteParams\XStreamResponse|null $xStreamResponse = null, ?RequestOptions $requestOptions = null, - ): mixed { + ): SessionExecuteResponse { $params = Util::removeNulls( [ - 'body' => $body, + 'agentConfig' => $agentConfig, + 'executeOptions' => $executeOptions, + 'frameID' => $frameID, 'xLanguage' => $xLanguage, 'xSDKVersion' => $xSDKVersion, 'xSentAt' => $xSentAt, @@ -134,7 +177,7 @@ public function executeAgent( ); // @phpstan-ignore-next-line argument.type - $response = $this->raw->executeAgent($id, params: $params, requestOptions: $requestOptions); + $response = $this->raw->execute($id, params: $params, requestOptions: $requestOptions); return $response->parse(); } @@ -144,27 +187,40 @@ public function executeAgent( * * Extracts structured data from the current page using AI-powered analysis. * - * @param mixed $id Path param: Unique session identifier - * @param mixed $body Body param: - * @param mixed $xLanguage Header param: Client SDK language - * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK - * @param mixed $xSentAt Header param: ISO timestamp when request was sent - * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * @param string $id Path param: Unique session identifier + * @param string $frameID Body param: Target frame ID for the extraction + * @param string $instruction Body param: Natural language instruction for what to extract + * @param array{ + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * selector?: string, + * timeout?: float, + * } $options Body param: + * @param array $schema Body param: JSON Schema defining the structure of data to extract + * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionExtractParams\XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|\Stagehand\Sessions\SessionExtractParams\XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE * * @throws APIException */ public function extract( - mixed $id, - mixed $body = null, - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, + string $id, + ?string $frameID = null, + ?string $instruction = null, + ?array $options = null, + ?array $schema = null, + string|\Stagehand\Sessions\SessionExtractParams\XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|\Stagehand\Sessions\SessionExtractParams\XStreamResponse|null $xStreamResponse = null, ?RequestOptions $requestOptions = null, - ): mixed { + ): SessionExtractResponse { $params = Util::removeNulls( [ - 'body' => $body, + 'frameID' => $frameID, + 'instruction' => $instruction, + 'options' => $options, + 'schema' => $schema, 'xLanguage' => $xLanguage, 'xSDKVersion' => $xSDKVersion, 'xSentAt' => $xSentAt, @@ -183,27 +239,37 @@ public function extract( * * Navigates the browser to the specified URL. * - * @param mixed $id Path param: Unique session identifier - * @param mixed $body Body param: - * @param mixed $xLanguage Header param: Client SDK language - * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK - * @param mixed $xSentAt Header param: ISO timestamp when request was sent - * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * @param string $id Path param: Unique session identifier + * @param string $url Body param: URL to navigate to + * @param string $frameID Body param: Target frame ID for the navigation + * @param array{ + * referer?: string, + * timeout?: float, + * waitUntil?: 'load'|'domcontentloaded'|'networkidle'|WaitUntil, + * } $options Body param: + * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionNavigateParams\XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|\Stagehand\Sessions\SessionNavigateParams\XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE * * @throws APIException */ public function navigate( - mixed $id, - mixed $body = null, - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, + string $id, + string $url, + ?string $frameID = null, + ?array $options = null, + string|\Stagehand\Sessions\SessionNavigateParams\XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|\Stagehand\Sessions\SessionNavigateParams\XStreamResponse|null $xStreamResponse = null, ?RequestOptions $requestOptions = null, - ): mixed { + ): SessionNavigateResponse { $params = Util::removeNulls( [ - 'body' => $body, + 'url' => $url, + 'frameID' => $frameID, + 'options' => $options, 'xLanguage' => $xLanguage, 'xSDKVersion' => $xSDKVersion, 'xSentAt' => $xSentAt, @@ -222,27 +288,37 @@ public function navigate( * * Identifies and returns available actions on the current page that match the given instruction. * - * @param mixed $id Path param: Unique session identifier - * @param mixed $body Body param: - * @param mixed $xLanguage Header param: Client SDK language - * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK - * @param mixed $xSentAt Header param: ISO timestamp when request was sent - * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * @param string $id Path param: Unique session identifier + * @param string $frameID Body param: Target frame ID for the observation + * @param string $instruction Body param: Natural language instruction for what actions to find + * @param array{ + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * selector?: string, + * timeout?: float, + * } $options Body param: + * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionObserveParams\XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|\Stagehand\Sessions\SessionObserveParams\XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE * * @throws APIException */ public function observe( - mixed $id, - mixed $body = null, - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, + string $id, + ?string $frameID = null, + ?string $instruction = null, + ?array $options = null, + string|\Stagehand\Sessions\SessionObserveParams\XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|\Stagehand\Sessions\SessionObserveParams\XStreamResponse|null $xStreamResponse = null, ?RequestOptions $requestOptions = null, - ): mixed { + ): SessionObserveResponse { $params = Util::removeNulls( [ - 'body' => $body, + 'frameID' => $frameID, + 'instruction' => $instruction, + 'options' => $options, 'xLanguage' => $xLanguage, 'xSDKVersion' => $xSDKVersion, 'xSentAt' => $xSentAt, @@ -261,25 +337,111 @@ public function observe( * * Creates a new browser session with the specified configuration. Returns a session ID used for all subsequent operations. * - * @param mixed $body Body param: - * @param mixed $xLanguage Header param: Client SDK language - * @param mixed $xSDKVersion Header param: Version of the Stagehand SDK - * @param mixed $xSentAt Header param: ISO timestamp when request was sent - * @param mixed $xStreamResponse Header param: Whether to stream the response via SSE + * @param string $modelName Body param: Model name to use for AI operations + * @param float $actTimeoutMs Body param: Timeout in ms for act operations + * @param array{ + * cdpURL?: string, + * launchOptions?: array{ + * acceptDownloads?: bool, + * args?: list, + * cdpURL?: string, + * chromiumSandbox?: bool, + * connectTimeoutMs?: float, + * deviceScaleFactor?: float, + * devtools?: bool, + * downloadsPath?: string, + * executablePath?: string, + * hasTouch?: bool, + * headless?: bool, + * ignoreDefaultArgs?: bool|list, + * ignoreHTTPSErrors?: bool, + * locale?: string, + * preserveUserDataDir?: bool, + * proxy?: array{ + * server: string, bypass?: string, password?: string, username?: string + * }, + * userDataDir?: string, + * viewport?: array{height: float, width: float}, + * }, + * type?: 'local'|'browserbase'|Type, + * } $browser Body param: + * @param array{ + * browserSettings?: array{ + * advancedStealth?: bool, + * blockAds?: bool, + * context?: array{id: string, persist?: bool}, + * extensionID?: string, + * fingerprint?: array{ + * browsers?: list<'chrome'|'edge'|'firefox'|'safari'|Browser>, + * devices?: list<'desktop'|'mobile'|Device>, + * httpVersion?: '1'|'2'|HTTPVersion, + * locales?: list, + * operatingSystems?: list<'android'|'ios'|'linux'|'macos'|'windows'|OperatingSystem>, + * screen?: array{ + * maxHeight?: float, maxWidth?: float, minHeight?: float, minWidth?: float + * }, + * }, + * logSession?: bool, + * recordSession?: bool, + * solveCaptchas?: bool, + * viewport?: array{height?: float, width?: float}, + * }, + * extensionID?: string, + * keepAlive?: bool, + * projectID?: string, + * proxies?: bool|list>, + * region?: 'us-west-2'|'us-east-1'|'eu-central-1'|'ap-southeast-1'|Region, + * timeout?: float, + * userMetadata?: array, + * } $browserbaseSessionCreateParams Body param: + * @param string $browserbaseSessionID Body param: Existing Browserbase session ID to resume + * @param bool $debugDom Body param: + * @param float $domSettleTimeoutMs Body param: Timeout in ms to wait for DOM to settle + * @param bool $experimental Body param: + * @param bool $selfHeal Body param: Enable self-healing for failed actions + * @param string $systemPrompt Body param: Custom system prompt for AI operations + * @param float $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) + * @param bool $waitForCaptchaSolves Body param: + * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionStartParams\XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|\Stagehand\Sessions\SessionStartParams\XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE * * @throws APIException */ public function start( - mixed $body = null, - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, + string $modelName, + ?float $actTimeoutMs = null, + ?array $browser = null, + ?array $browserbaseSessionCreateParams = null, + ?string $browserbaseSessionID = null, + ?bool $debugDom = null, + ?float $domSettleTimeoutMs = null, + ?bool $experimental = null, + ?bool $selfHeal = null, + ?string $systemPrompt = null, + ?float $verbose = null, + ?bool $waitForCaptchaSolves = null, + string|\Stagehand\Sessions\SessionStartParams\XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|\Stagehand\Sessions\SessionStartParams\XStreamResponse|null $xStreamResponse = null, ?RequestOptions $requestOptions = null, - ): mixed { + ): SessionStartResponse { $params = Util::removeNulls( [ - 'body' => $body, + 'modelName' => $modelName, + 'actTimeoutMs' => $actTimeoutMs, + 'browser' => $browser, + 'browserbaseSessionCreateParams' => $browserbaseSessionCreateParams, + 'browserbaseSessionID' => $browserbaseSessionID, + 'debugDom' => $debugDom, + 'domSettleTimeoutMs' => $domSettleTimeoutMs, + 'experimental' => $experimental, + 'selfHeal' => $selfHeal, + 'systemPrompt' => $systemPrompt, + 'verbose' => $verbose, + 'waitForCaptchaSolves' => $waitForCaptchaSolves, 'xLanguage' => $xLanguage, 'xSDKVersion' => $xSDKVersion, 'xSentAt' => $xSentAt, diff --git a/src/Sessions/SessionActParams.php b/src/Sessions/SessionActParams.php index a1240b1..979430b 100644 --- a/src/Sessions/SessionActParams.php +++ b/src/Sessions/SessionActParams.php @@ -5,21 +5,31 @@ namespace Stagehand\Sessions; use Stagehand\Core\Attributes\Optional; +use Stagehand\Core\Attributes\Required; use Stagehand\Core\Concerns\SdkModel; use Stagehand\Core\Concerns\SdkParams; use Stagehand\Core\Contracts\BaseModel; +use Stagehand\Sessions\SessionActParams\Input\ActionInput; +use Stagehand\Sessions\SessionActParams\Options; +use Stagehand\Sessions\SessionActParams\XLanguage; +use Stagehand\Sessions\SessionActParams\XStreamResponse; /** * Executes a browser action using natural language instructions or a predefined Action object. * * @see Stagehand\Services\SessionsService::act() * + * @phpstan-import-type InputShape from \Stagehand\Sessions\SessionActParams\Input + * @phpstan-import-type OptionsShape from \Stagehand\Sessions\SessionActParams\Options + * * @phpstan-type SessionActParamsShape = array{ - * body?: mixed, - * xLanguage?: mixed, - * xSDKVersion?: mixed, - * xSentAt?: mixed, - * xStreamResponse?: mixed, + * input: InputShape, + * frameID?: string|null, + * options?: OptionsShape|null, + * xLanguage?: null|XLanguage|value-of, + * xSDKVersion?: string|null, + * xSentAt?: \DateTimeInterface|null, + * xStreamResponse?: null|XStreamResponse|value-of, * } */ final class SessionActParams implements BaseModel @@ -28,21 +38,63 @@ final class SessionActParams implements BaseModel use SdkModel; use SdkParams; - #[Optional] - public mixed $body; + /** + * Natural language instruction or Action object. + */ + #[Required] + public string|ActionInput $input; - #[Optional] - public mixed $xLanguage; + /** + * Target frame ID for the action. + */ + #[Optional('frameId')] + public ?string $frameID; #[Optional] - public mixed $xSDKVersion; + public ?Options $options; + /** + * Client SDK language. + * + * @var value-of|null $xLanguage + */ + #[Optional(enum: XLanguage::class)] + public ?string $xLanguage; + + /** + * Version of the Stagehand SDK. + */ #[Optional] - public mixed $xSentAt; + public ?string $xSDKVersion; + /** + * ISO timestamp when request was sent. + */ #[Optional] - public mixed $xStreamResponse; + public ?\DateTimeInterface $xSentAt; + /** + * Whether to stream the response via SSE. + * + * @var value-of|null $xStreamResponse + */ + #[Optional(enum: XStreamResponse::class)] + public ?string $xStreamResponse; + + /** + * `new SessionActParams()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * SessionActParams::with(input: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new SessionActParams)->withInput(...) + * ``` + */ public function __construct() { $this->initialize(); @@ -52,17 +104,27 @@ public function __construct() * Construct an instance from the required parameters. * * You must use named parameters to construct any parameters with a default value. + * + * @param InputShape $input + * @param OptionsShape $options + * @param XLanguage|value-of $xLanguage + * @param XStreamResponse|value-of $xStreamResponse */ public static function with( - mixed $body = null, - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, + string|ActionInput|array $input, + ?string $frameID = null, + Options|array|null $options = null, + XLanguage|string|null $xLanguage = null, + ?string $xSDKVersion = null, + ?\DateTimeInterface $xSentAt = null, + XStreamResponse|string|null $xStreamResponse = null, ): self { $self = new self; - null !== $body && $self['body'] = $body; + $self['input'] = $input; + + null !== $frameID && $self['frameID'] = $frameID; + null !== $options && $self['options'] = $options; null !== $xLanguage && $self['xLanguage'] = $xLanguage; null !== $xSDKVersion && $self['xSDKVersion'] = $xSDKVersion; null !== $xSentAt && $self['xSentAt'] = $xSentAt; @@ -71,15 +133,47 @@ public static function with( return $self; } - public function withBody(mixed $body): self + /** + * Natural language instruction or Action object. + * + * @param InputShape $input + */ + public function withInput(string|ActionInput|array $input): self { $self = clone $this; - $self['body'] = $body; + $self['input'] = $input; return $self; } - public function withXLanguage(mixed $xLanguage): self + /** + * Target frame ID for the action. + */ + public function withFrameID(string $frameID): self + { + $self = clone $this; + $self['frameID'] = $frameID; + + return $self; + } + + /** + * @param OptionsShape $options + */ + public function withOptions(Options|array $options): self + { + $self = clone $this; + $self['options'] = $options; + + return $self; + } + + /** + * Client SDK language. + * + * @param XLanguage|value-of $xLanguage + */ + public function withXLanguage(XLanguage|string $xLanguage): self { $self = clone $this; $self['xLanguage'] = $xLanguage; @@ -87,7 +181,10 @@ public function withXLanguage(mixed $xLanguage): self return $self; } - public function withXSDKVersion(mixed $xSDKVersion): self + /** + * Version of the Stagehand SDK. + */ + public function withXSDKVersion(string $xSDKVersion): self { $self = clone $this; $self['xSDKVersion'] = $xSDKVersion; @@ -95,7 +192,10 @@ public function withXSDKVersion(mixed $xSDKVersion): self return $self; } - public function withXSentAt(mixed $xSentAt): self + /** + * ISO timestamp when request was sent. + */ + public function withXSentAt(\DateTimeInterface $xSentAt): self { $self = clone $this; $self['xSentAt'] = $xSentAt; @@ -103,8 +203,14 @@ public function withXSentAt(mixed $xSentAt): self return $self; } - public function withXStreamResponse(mixed $xStreamResponse): self - { + /** + * Whether to stream the response via SSE. + * + * @param XStreamResponse|value-of $xStreamResponse + */ + public function withXStreamResponse( + XStreamResponse|string $xStreamResponse + ): self { $self = clone $this; $self['xStreamResponse'] = $xStreamResponse; diff --git a/src/Sessions/SessionActParams/Input.php b/src/Sessions/SessionActParams/Input.php new file mode 100644 index 0000000..8a338a4 --- /dev/null +++ b/src/Sessions/SessionActParams/Input.php @@ -0,0 +1,30 @@ +|array + */ + public static function variants(): array + { + return ['string', ActionInput::class]; + } +} diff --git a/src/Sessions/SessionActParams/Input/ActionInput.php b/src/Sessions/SessionActParams/Input/ActionInput.php new file mode 100644 index 0000000..e5a16c0 --- /dev/null +++ b/src/Sessions/SessionActParams/Input/ActionInput.php @@ -0,0 +1,141 @@ +|null, + * method?: string|null, + * } + */ +final class ActionInput implements BaseModel +{ + /** @use SdkModel */ + use SdkModel; + + /** + * Human-readable description of the action. + */ + #[Required] + public string $description; + + /** + * CSS selector or XPath for the element. + */ + #[Required] + public string $selector; + + /** + * Arguments to pass to the method. + * + * @var list|null $arguments + */ + #[Optional(list: 'string')] + public ?array $arguments; + + /** + * The method to execute (click, fill, etc.). + */ + #[Optional] + public ?string $method; + + /** + * `new ActionInput()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * ActionInput::with(description: ..., selector: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new ActionInput)->withDescription(...)->withSelector(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param list $arguments + */ + public static function with( + string $description, + string $selector, + ?array $arguments = null, + ?string $method = null, + ): self { + $self = new self; + + $self['description'] = $description; + $self['selector'] = $selector; + + null !== $arguments && $self['arguments'] = $arguments; + null !== $method && $self['method'] = $method; + + return $self; + } + + /** + * Human-readable description of the action. + */ + public function withDescription(string $description): self + { + $self = clone $this; + $self['description'] = $description; + + return $self; + } + + /** + * CSS selector or XPath for the element. + */ + public function withSelector(string $selector): self + { + $self = clone $this; + $self['selector'] = $selector; + + return $self; + } + + /** + * Arguments to pass to the method. + * + * @param list $arguments + */ + public function withArguments(array $arguments): self + { + $self = clone $this; + $self['arguments'] = $arguments; + + return $self; + } + + /** + * The method to execute (click, fill, etc.). + */ + public function withMethod(string $method): self + { + $self = clone $this; + $self['method'] = $method; + + return $self; + } +} diff --git a/src/Sessions/SessionActParams/Options.php b/src/Sessions/SessionActParams/Options.php new file mode 100644 index 0000000..0113bf2 --- /dev/null +++ b/src/Sessions/SessionActParams/Options.php @@ -0,0 +1,104 @@ +|null, + * } + */ +final class Options implements BaseModel +{ + /** @use SdkModel */ + use SdkModel; + + #[Optional] + public string|UnionMember1|null $model; + + /** + * Timeout in ms for the action. + */ + #[Optional] + public ?float $timeout; + + /** + * Variables to substitute in the action instruction. + * + * @var array|null $variables + */ + #[Optional(map: 'string')] + public ?array $variables; + + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param ModelConfigShape $model + * @param array $variables + */ + public static function with( + string|UnionMember1|array|null $model = null, + ?float $timeout = null, + ?array $variables = null, + ): self { + $self = new self; + + null !== $model && $self['model'] = $model; + null !== $timeout && $self['timeout'] = $timeout; + null !== $variables && $self['variables'] = $variables; + + return $self; + } + + /** + * @param ModelConfigShape $model + */ + public function withModel(string|UnionMember1|array $model): self + { + $self = clone $this; + $self['model'] = $model; + + return $self; + } + + /** + * Timeout in ms for the action. + */ + public function withTimeout(float $timeout): self + { + $self = clone $this; + $self['timeout'] = $timeout; + + return $self; + } + + /** + * Variables to substitute in the action instruction. + * + * @param array $variables + */ + public function withVariables(array $variables): self + { + $self = clone $this; + $self['variables'] = $variables; + + return $self; + } +} diff --git a/src/Sessions/SessionActParams/XLanguage.php b/src/Sessions/SessionActParams/XLanguage.php new file mode 100644 index 0000000..a13d848 --- /dev/null +++ b/src/Sessions/SessionActParams/XLanguage.php @@ -0,0 +1,17 @@ + */ + use SdkModel; + + #[Required] + public Data $data; + + #[Required] + public bool $success; + + /** + * `new SessionActResponse()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * SessionActResponse::with(data: ..., success: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new SessionActResponse)->withData(...)->withSuccess(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param DataShape $data + */ + public static function with(Data|array $data, bool $success): self + { + $self = new self; + + $self['data'] = $data; + $self['success'] = $success; + + return $self; + } + + /** + * @param DataShape $data + */ + public function withData(Data|array $data): self + { + $self = clone $this; + $self['data'] = $data; + + return $self; + } + + public function withSuccess(bool $success): self + { + $self = clone $this; + $self['success'] = $success; + + return $self; + } +} diff --git a/src/Sessions/SessionActResponse/Data.php b/src/Sessions/SessionActResponse/Data.php new file mode 100644 index 0000000..8322851 --- /dev/null +++ b/src/Sessions/SessionActResponse/Data.php @@ -0,0 +1,94 @@ + */ + use SdkModel; + + #[Required] + public Result $result; + + /** + * Action ID for tracking. + */ + #[Optional('actionId')] + public ?string $actionID; + + /** + * `new Data()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * Data::with(result: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new Data)->withResult(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param ResultShape $result + */ + public static function with( + Result|array $result, + ?string $actionID = null + ): self { + $self = new self; + + $self['result'] = $result; + + null !== $actionID && $self['actionID'] = $actionID; + + return $self; + } + + /** + * @param ResultShape $result + */ + public function withResult(Result|array $result): self + { + $self = clone $this; + $self['result'] = $result; + + return $self; + } + + /** + * Action ID for tracking. + */ + public function withActionID(string $actionID): self + { + $self = clone $this; + $self['actionID'] = $actionID; + + return $self; + } +} diff --git a/src/Sessions/SessionActResponse/Data/Result.php b/src/Sessions/SessionActResponse/Data/Result.php new file mode 100644 index 0000000..ed4ecdb --- /dev/null +++ b/src/Sessions/SessionActResponse/Data/Result.php @@ -0,0 +1,144 @@ +, + * message: string, + * success: bool, + * } + */ +final class Result implements BaseModel +{ + /** @use SdkModel */ + use SdkModel; + + /** + * Description of the action that was performed. + */ + #[Required] + public string $actionDescription; + + /** + * List of actions that were executed. + * + * @var list $actions + */ + #[Required(list: Action::class)] + public array $actions; + + /** + * Human-readable result message. + */ + #[Required] + public string $message; + + /** + * Whether the action completed successfully. + */ + #[Required] + public bool $success; + + /** + * `new Result()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * Result::with(actionDescription: ..., actions: ..., message: ..., success: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new Result) + * ->withActionDescription(...) + * ->withActions(...) + * ->withMessage(...) + * ->withSuccess(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param list $actions + */ + public static function with( + string $actionDescription, + array $actions, + string $message, + bool $success + ): self { + $self = new self; + + $self['actionDescription'] = $actionDescription; + $self['actions'] = $actions; + $self['message'] = $message; + $self['success'] = $success; + + return $self; + } + + /** + * Description of the action that was performed. + */ + public function withActionDescription(string $actionDescription): self + { + $self = clone $this; + $self['actionDescription'] = $actionDescription; + + return $self; + } + + /** + * List of actions that were executed. + * + * @param list $actions + */ + public function withActions(array $actions): self + { + $self = clone $this; + $self['actions'] = $actions; + + return $self; + } + + /** + * Human-readable result message. + */ + public function withMessage(string $message): self + { + $self = clone $this; + $self['message'] = $message; + + return $self; + } + + /** + * Whether the action completed successfully. + */ + public function withSuccess(bool $success): self + { + $self = clone $this; + $self['success'] = $success; + + return $self; + } +} diff --git a/src/Sessions/SessionEndParams.php b/src/Sessions/SessionEndParams.php index 7c40b6d..243b0dd 100644 --- a/src/Sessions/SessionEndParams.php +++ b/src/Sessions/SessionEndParams.php @@ -8,6 +8,8 @@ use Stagehand\Core\Concerns\SdkModel; use Stagehand\Core\Concerns\SdkParams; use Stagehand\Core\Contracts\BaseModel; +use Stagehand\Sessions\SessionEndParams\XLanguage; +use Stagehand\Sessions\SessionEndParams\XStreamResponse; /** * Terminates the browser session and releases all associated resources. @@ -15,10 +17,10 @@ * @see Stagehand\Services\SessionsService::end() * * @phpstan-type SessionEndParamsShape = array{ - * xLanguage?: mixed, - * xSDKVersion?: mixed, - * xSentAt?: mixed, - * xStreamResponse?: mixed, + * xLanguage?: null|XLanguage|value-of, + * xSDKVersion?: string|null, + * xSentAt?: \DateTimeInterface|null, + * xStreamResponse?: null|XStreamResponse|value-of, * } */ final class SessionEndParams implements BaseModel @@ -27,17 +29,33 @@ final class SessionEndParams implements BaseModel use SdkModel; use SdkParams; - #[Optional] - public mixed $xLanguage; + /** + * Client SDK language. + * + * @var value-of|null $xLanguage + */ + #[Optional(enum: XLanguage::class)] + public ?string $xLanguage; + /** + * Version of the Stagehand SDK. + */ #[Optional] - public mixed $xSDKVersion; + public ?string $xSDKVersion; + /** + * ISO timestamp when request was sent. + */ #[Optional] - public mixed $xSentAt; + public ?\DateTimeInterface $xSentAt; - #[Optional] - public mixed $xStreamResponse; + /** + * Whether to stream the response via SSE. + * + * @var value-of|null $xStreamResponse + */ + #[Optional(enum: XStreamResponse::class)] + public ?string $xStreamResponse; public function __construct() { @@ -48,12 +66,15 @@ public function __construct() * Construct an instance from the required parameters. * * You must use named parameters to construct any parameters with a default value. + * + * @param XLanguage|value-of $xLanguage + * @param XStreamResponse|value-of $xStreamResponse */ public static function with( - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, + XLanguage|string|null $xLanguage = null, + ?string $xSDKVersion = null, + ?\DateTimeInterface $xSentAt = null, + XStreamResponse|string|null $xStreamResponse = null, ): self { $self = new self; @@ -65,7 +86,12 @@ public static function with( return $self; } - public function withXLanguage(mixed $xLanguage): self + /** + * Client SDK language. + * + * @param XLanguage|value-of $xLanguage + */ + public function withXLanguage(XLanguage|string $xLanguage): self { $self = clone $this; $self['xLanguage'] = $xLanguage; @@ -73,7 +99,10 @@ public function withXLanguage(mixed $xLanguage): self return $self; } - public function withXSDKVersion(mixed $xSDKVersion): self + /** + * Version of the Stagehand SDK. + */ + public function withXSDKVersion(string $xSDKVersion): self { $self = clone $this; $self['xSDKVersion'] = $xSDKVersion; @@ -81,7 +110,10 @@ public function withXSDKVersion(mixed $xSDKVersion): self return $self; } - public function withXSentAt(mixed $xSentAt): self + /** + * ISO timestamp when request was sent. + */ + public function withXSentAt(\DateTimeInterface $xSentAt): self { $self = clone $this; $self['xSentAt'] = $xSentAt; @@ -89,8 +121,14 @@ public function withXSentAt(mixed $xSentAt): self return $self; } - public function withXStreamResponse(mixed $xStreamResponse): self - { + /** + * Whether to stream the response via SSE. + * + * @param XStreamResponse|value-of $xStreamResponse + */ + public function withXStreamResponse( + XStreamResponse|string $xStreamResponse + ): self { $self = clone $this; $self['xStreamResponse'] = $xStreamResponse; diff --git a/src/Sessions/SessionEndParams/XLanguage.php b/src/Sessions/SessionEndParams/XLanguage.php new file mode 100644 index 0000000..0857a8f --- /dev/null +++ b/src/Sessions/SessionEndParams/XLanguage.php @@ -0,0 +1,17 @@ + */ + use SdkModel; + + #[Required] + public bool $success; + + /** + * `new SessionEndResponse()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * SessionEndResponse::with(success: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new SessionEndResponse)->withSuccess(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with(bool $success): self + { + $self = new self; + + $self['success'] = $success; + + return $self; + } + + public function withSuccess(bool $success): self + { + $self = clone $this; + $self['success'] = $success; + + return $self; + } +} diff --git a/src/Sessions/SessionExecuteAgentParams.php b/src/Sessions/SessionExecuteAgentParams.php deleted file mode 100644 index 379e90a..0000000 --- a/src/Sessions/SessionExecuteAgentParams.php +++ /dev/null @@ -1,113 +0,0 @@ - */ - use SdkModel; - use SdkParams; - - #[Optional] - public mixed $body; - - #[Optional] - public mixed $xLanguage; - - #[Optional] - public mixed $xSDKVersion; - - #[Optional] - public mixed $xSentAt; - - #[Optional] - public mixed $xStreamResponse; - - public function __construct() - { - $this->initialize(); - } - - /** - * Construct an instance from the required parameters. - * - * You must use named parameters to construct any parameters with a default value. - */ - public static function with( - mixed $body = null, - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, - ): self { - $self = new self; - - null !== $body && $self['body'] = $body; - null !== $xLanguage && $self['xLanguage'] = $xLanguage; - null !== $xSDKVersion && $self['xSDKVersion'] = $xSDKVersion; - null !== $xSentAt && $self['xSentAt'] = $xSentAt; - null !== $xStreamResponse && $self['xStreamResponse'] = $xStreamResponse; - - return $self; - } - - public function withBody(mixed $body): self - { - $self = clone $this; - $self['body'] = $body; - - return $self; - } - - public function withXLanguage(mixed $xLanguage): self - { - $self = clone $this; - $self['xLanguage'] = $xLanguage; - - return $self; - } - - public function withXSDKVersion(mixed $xSDKVersion): self - { - $self = clone $this; - $self['xSDKVersion'] = $xSDKVersion; - - return $self; - } - - public function withXSentAt(mixed $xSentAt): self - { - $self = clone $this; - $self['xSentAt'] = $xSentAt; - - return $self; - } - - public function withXStreamResponse(mixed $xStreamResponse): self - { - $self = clone $this; - $self['xStreamResponse'] = $xStreamResponse; - - return $self; - } -} diff --git a/src/Sessions/SessionExecuteParams.php b/src/Sessions/SessionExecuteParams.php new file mode 100644 index 0000000..b700f0a --- /dev/null +++ b/src/Sessions/SessionExecuteParams.php @@ -0,0 +1,215 @@ +, + * xSDKVersion?: string|null, + * xSentAt?: \DateTimeInterface|null, + * xStreamResponse?: null|XStreamResponse|value-of, + * } + */ +final class SessionExecuteParams implements BaseModel +{ + /** @use SdkModel */ + use SdkModel; + use SdkParams; + + #[Required] + public AgentConfig $agentConfig; + + #[Required] + public ExecuteOptions $executeOptions; + + /** + * Target frame ID for the agent. + */ + #[Optional('frameId')] + public ?string $frameID; + + /** + * Client SDK language. + * + * @var value-of|null $xLanguage + */ + #[Optional(enum: XLanguage::class)] + public ?string $xLanguage; + + /** + * Version of the Stagehand SDK. + */ + #[Optional] + public ?string $xSDKVersion; + + /** + * ISO timestamp when request was sent. + */ + #[Optional] + public ?\DateTimeInterface $xSentAt; + + /** + * Whether to stream the response via SSE. + * + * @var value-of|null $xStreamResponse + */ + #[Optional(enum: XStreamResponse::class)] + public ?string $xStreamResponse; + + /** + * `new SessionExecuteParams()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * SessionExecuteParams::with(agentConfig: ..., executeOptions: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new SessionExecuteParams)->withAgentConfig(...)->withExecuteOptions(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param AgentConfigShape $agentConfig + * @param ExecuteOptionsShape $executeOptions + * @param XLanguage|value-of $xLanguage + * @param XStreamResponse|value-of $xStreamResponse + */ + public static function with( + AgentConfig|array $agentConfig, + ExecuteOptions|array $executeOptions, + ?string $frameID = null, + XLanguage|string|null $xLanguage = null, + ?string $xSDKVersion = null, + ?\DateTimeInterface $xSentAt = null, + XStreamResponse|string|null $xStreamResponse = null, + ): self { + $self = new self; + + $self['agentConfig'] = $agentConfig; + $self['executeOptions'] = $executeOptions; + + null !== $frameID && $self['frameID'] = $frameID; + null !== $xLanguage && $self['xLanguage'] = $xLanguage; + null !== $xSDKVersion && $self['xSDKVersion'] = $xSDKVersion; + null !== $xSentAt && $self['xSentAt'] = $xSentAt; + null !== $xStreamResponse && $self['xStreamResponse'] = $xStreamResponse; + + return $self; + } + + /** + * @param AgentConfigShape $agentConfig + */ + public function withAgentConfig(AgentConfig|array $agentConfig): self + { + $self = clone $this; + $self['agentConfig'] = $agentConfig; + + return $self; + } + + /** + * @param ExecuteOptionsShape $executeOptions + */ + public function withExecuteOptions( + ExecuteOptions|array $executeOptions + ): self { + $self = clone $this; + $self['executeOptions'] = $executeOptions; + + return $self; + } + + /** + * Target frame ID for the agent. + */ + public function withFrameID(string $frameID): self + { + $self = clone $this; + $self['frameID'] = $frameID; + + return $self; + } + + /** + * Client SDK language. + * + * @param XLanguage|value-of $xLanguage + */ + public function withXLanguage(XLanguage|string $xLanguage): self + { + $self = clone $this; + $self['xLanguage'] = $xLanguage; + + return $self; + } + + /** + * Version of the Stagehand SDK. + */ + public function withXSDKVersion(string $xSDKVersion): self + { + $self = clone $this; + $self['xSDKVersion'] = $xSDKVersion; + + return $self; + } + + /** + * ISO timestamp when request was sent. + */ + public function withXSentAt(\DateTimeInterface $xSentAt): self + { + $self = clone $this; + $self['xSentAt'] = $xSentAt; + + return $self; + } + + /** + * Whether to stream the response via SSE. + * + * @param XStreamResponse|value-of $xStreamResponse + */ + public function withXStreamResponse( + XStreamResponse|string $xStreamResponse + ): self { + $self = clone $this; + $self['xStreamResponse'] = $xStreamResponse; + + return $self; + } +} diff --git a/src/Sessions/SessionExecuteParams/AgentConfig.php b/src/Sessions/SessionExecuteParams/AgentConfig.php new file mode 100644 index 0000000..7fef271 --- /dev/null +++ b/src/Sessions/SessionExecuteParams/AgentConfig.php @@ -0,0 +1,97 @@ + */ + use SdkModel; + + /** + * Enable Computer Use Agent mode. + */ + #[Optional] + public ?bool $cua; + + #[Optional] + public string|UnionMember1|null $model; + + /** + * Custom system prompt for the agent. + */ + #[Optional] + public ?string $systemPrompt; + + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param ModelConfigShape $model + */ + public static function with( + ?bool $cua = null, + string|UnionMember1|array|null $model = null, + ?string $systemPrompt = null, + ): self { + $self = new self; + + null !== $cua && $self['cua'] = $cua; + null !== $model && $self['model'] = $model; + null !== $systemPrompt && $self['systemPrompt'] = $systemPrompt; + + return $self; + } + + /** + * Enable Computer Use Agent mode. + */ + public function withCua(bool $cua): self + { + $self = clone $this; + $self['cua'] = $cua; + + return $self; + } + + /** + * @param ModelConfigShape $model + */ + public function withModel(string|UnionMember1|array $model): self + { + $self = clone $this; + $self['model'] = $model; + + return $self; + } + + /** + * Custom system prompt for the agent. + */ + public function withSystemPrompt(string $systemPrompt): self + { + $self = clone $this; + $self['systemPrompt'] = $systemPrompt; + + return $self; + } +} diff --git a/src/Sessions/SessionExecuteParams/ExecuteOptions.php b/src/Sessions/SessionExecuteParams/ExecuteOptions.php new file mode 100644 index 0000000..c5e676f --- /dev/null +++ b/src/Sessions/SessionExecuteParams/ExecuteOptions.php @@ -0,0 +1,111 @@ + */ + use SdkModel; + + /** + * Natural language instruction for the agent. + */ + #[Required] + public string $instruction; + + /** + * Whether to visually highlight the cursor during execution. + */ + #[Optional] + public ?bool $highlightCursor; + + /** + * Maximum number of steps the agent can take. + */ + #[Optional] + public ?float $maxSteps; + + /** + * `new ExecuteOptions()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * ExecuteOptions::with(instruction: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new ExecuteOptions)->withInstruction(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with( + string $instruction, + ?bool $highlightCursor = null, + ?float $maxSteps = null + ): self { + $self = new self; + + $self['instruction'] = $instruction; + + null !== $highlightCursor && $self['highlightCursor'] = $highlightCursor; + null !== $maxSteps && $self['maxSteps'] = $maxSteps; + + return $self; + } + + /** + * Natural language instruction for the agent. + */ + public function withInstruction(string $instruction): self + { + $self = clone $this; + $self['instruction'] = $instruction; + + return $self; + } + + /** + * Whether to visually highlight the cursor during execution. + */ + public function withHighlightCursor(bool $highlightCursor): self + { + $self = clone $this; + $self['highlightCursor'] = $highlightCursor; + + return $self; + } + + /** + * Maximum number of steps the agent can take. + */ + public function withMaxSteps(float $maxSteps): self + { + $self = clone $this; + $self['maxSteps'] = $maxSteps; + + return $self; + } +} diff --git a/src/Sessions/SessionExecuteParams/XLanguage.php b/src/Sessions/SessionExecuteParams/XLanguage.php new file mode 100644 index 0000000..26ef015 --- /dev/null +++ b/src/Sessions/SessionExecuteParams/XLanguage.php @@ -0,0 +1,17 @@ + */ + use SdkModel; + + #[Required] + public Data $data; + + #[Required] + public bool $success; + + /** + * `new SessionExecuteResponse()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * SessionExecuteResponse::with(data: ..., success: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new SessionExecuteResponse)->withData(...)->withSuccess(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param DataShape $data + */ + public static function with(Data|array $data, bool $success): self + { + $self = new self; + + $self['data'] = $data; + $self['success'] = $success; + + return $self; + } + + /** + * @param DataShape $data + */ + public function withData(Data|array $data): self + { + $self = clone $this; + $self['data'] = $data; + + return $self; + } + + public function withSuccess(bool $success): self + { + $self = clone $this; + $self['success'] = $success; + + return $self; + } +} diff --git a/src/Sessions/SessionExecuteResponse/Data.php b/src/Sessions/SessionExecuteResponse/Data.php new file mode 100644 index 0000000..fe88bc4 --- /dev/null +++ b/src/Sessions/SessionExecuteResponse/Data.php @@ -0,0 +1,70 @@ + */ + use SdkModel; + + #[Required] + public Result $result; + + /** + * `new Data()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * Data::with(result: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new Data)->withResult(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param ResultShape $result + */ + public static function with(Result|array $result): self + { + $self = new self; + + $self['result'] = $result; + + return $self; + } + + /** + * @param ResultShape $result + */ + public function withResult(Result|array $result): self + { + $self = clone $this; + $self['result'] = $result; + + return $self; + } +} diff --git a/src/Sessions/SessionExecuteResponse/Data/Result.php b/src/Sessions/SessionExecuteResponse/Data/Result.php new file mode 100644 index 0000000..c8f8e55 --- /dev/null +++ b/src/Sessions/SessionExecuteResponse/Data/Result.php @@ -0,0 +1,179 @@ +, + * completed: bool, + * message: string, + * success: bool, + * metadata?: array|null, + * usage?: null|Usage|UsageShape, + * } + */ +final class Result implements BaseModel +{ + /** @use SdkModel */ + use SdkModel; + + /** @var list $actions */ + #[Required(list: Action::class)] + public array $actions; + + /** + * Whether the agent finished its task. + */ + #[Required] + public bool $completed; + + /** + * Summary of what the agent accomplished. + */ + #[Required] + public string $message; + + /** + * Whether the agent completed successfully. + */ + #[Required] + public bool $success; + + /** @var array|null $metadata */ + #[Optional(map: 'mixed')] + public ?array $metadata; + + #[Optional] + public ?Usage $usage; + + /** + * `new Result()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * Result::with(actions: ..., completed: ..., message: ..., success: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new Result) + * ->withActions(...) + * ->withCompleted(...) + * ->withMessage(...) + * ->withSuccess(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param list $actions + * @param array $metadata + * @param UsageShape $usage + */ + public static function with( + array $actions, + bool $completed, + string $message, + bool $success, + ?array $metadata = null, + Usage|array|null $usage = null, + ): self { + $self = new self; + + $self['actions'] = $actions; + $self['completed'] = $completed; + $self['message'] = $message; + $self['success'] = $success; + + null !== $metadata && $self['metadata'] = $metadata; + null !== $usage && $self['usage'] = $usage; + + return $self; + } + + /** + * @param list $actions + */ + public function withActions(array $actions): self + { + $self = clone $this; + $self['actions'] = $actions; + + return $self; + } + + /** + * Whether the agent finished its task. + */ + public function withCompleted(bool $completed): self + { + $self = clone $this; + $self['completed'] = $completed; + + return $self; + } + + /** + * Summary of what the agent accomplished. + */ + public function withMessage(string $message): self + { + $self = clone $this; + $self['message'] = $message; + + return $self; + } + + /** + * Whether the agent completed successfully. + */ + public function withSuccess(bool $success): self + { + $self = clone $this; + $self['success'] = $success; + + return $self; + } + + /** + * @param array $metadata + */ + public function withMetadata(array $metadata): self + { + $self = clone $this; + $self['metadata'] = $metadata; + + return $self; + } + + /** + * @param UsageShape $usage + */ + public function withUsage(Usage|array $usage): self + { + $self = clone $this; + $self['usage'] = $usage; + + return $self; + } +} diff --git a/src/Sessions/SessionExecuteResponse/Data/Result/Action.php b/src/Sessions/SessionExecuteResponse/Data/Result/Action.php new file mode 100644 index 0000000..042697d --- /dev/null +++ b/src/Sessions/SessionExecuteResponse/Data/Result/Action.php @@ -0,0 +1,183 @@ + */ + use SdkModel; + + /** + * Type of action taken. + */ + #[Required] + public string $type; + + #[Optional] + public ?string $action; + + #[Optional] + public ?string $instruction; + + #[Optional] + public ?string $pageText; + + #[Optional('pageUrl')] + public ?string $pageURL; + + /** + * Agent's reasoning for taking this action. + */ + #[Optional] + public ?string $reasoning; + + #[Optional] + public ?bool $taskCompleted; + + /** + * Time taken for this action in ms. + */ + #[Optional] + public ?float $timeMs; + + /** + * `new Action()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * Action::with(type: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new Action)->withType(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with( + string $type, + ?string $action = null, + ?string $instruction = null, + ?string $pageText = null, + ?string $pageURL = null, + ?string $reasoning = null, + ?bool $taskCompleted = null, + ?float $timeMs = null, + ): self { + $self = new self; + + $self['type'] = $type; + + null !== $action && $self['action'] = $action; + null !== $instruction && $self['instruction'] = $instruction; + null !== $pageText && $self['pageText'] = $pageText; + null !== $pageURL && $self['pageURL'] = $pageURL; + null !== $reasoning && $self['reasoning'] = $reasoning; + null !== $taskCompleted && $self['taskCompleted'] = $taskCompleted; + null !== $timeMs && $self['timeMs'] = $timeMs; + + return $self; + } + + /** + * Type of action taken. + */ + public function withType(string $type): self + { + $self = clone $this; + $self['type'] = $type; + + return $self; + } + + public function withAction(string $action): self + { + $self = clone $this; + $self['action'] = $action; + + return $self; + } + + public function withInstruction(string $instruction): self + { + $self = clone $this; + $self['instruction'] = $instruction; + + return $self; + } + + public function withPageText(string $pageText): self + { + $self = clone $this; + $self['pageText'] = $pageText; + + return $self; + } + + public function withPageURL(string $pageURL): self + { + $self = clone $this; + $self['pageURL'] = $pageURL; + + return $self; + } + + /** + * Agent's reasoning for taking this action. + */ + public function withReasoning(string $reasoning): self + { + $self = clone $this; + $self['reasoning'] = $reasoning; + + return $self; + } + + public function withTaskCompleted(bool $taskCompleted): self + { + $self = clone $this; + $self['taskCompleted'] = $taskCompleted; + + return $self; + } + + /** + * Time taken for this action in ms. + */ + public function withTimeMs(float $timeMs): self + { + $self = clone $this; + $self['timeMs'] = $timeMs; + + return $self; + } +} diff --git a/src/Sessions/SessionExecuteResponse/Data/Result/Usage.php b/src/Sessions/SessionExecuteResponse/Data/Result/Usage.php new file mode 100644 index 0000000..500be83 --- /dev/null +++ b/src/Sessions/SessionExecuteResponse/Data/Result/Usage.php @@ -0,0 +1,126 @@ + */ + use SdkModel; + + #[Required('inference_time_ms')] + public float $inferenceTimeMs; + + #[Required('input_tokens')] + public float $inputTokens; + + #[Required('output_tokens')] + public float $outputTokens; + + #[Optional('cached_input_tokens')] + public ?float $cachedInputTokens; + + #[Optional('reasoning_tokens')] + public ?float $reasoningTokens; + + /** + * `new Usage()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * Usage::with(inferenceTimeMs: ..., inputTokens: ..., outputTokens: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new Usage) + * ->withInferenceTimeMs(...) + * ->withInputTokens(...) + * ->withOutputTokens(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with( + float $inferenceTimeMs, + float $inputTokens, + float $outputTokens, + ?float $cachedInputTokens = null, + ?float $reasoningTokens = null, + ): self { + $self = new self; + + $self['inferenceTimeMs'] = $inferenceTimeMs; + $self['inputTokens'] = $inputTokens; + $self['outputTokens'] = $outputTokens; + + null !== $cachedInputTokens && $self['cachedInputTokens'] = $cachedInputTokens; + null !== $reasoningTokens && $self['reasoningTokens'] = $reasoningTokens; + + return $self; + } + + public function withInferenceTimeMs(float $inferenceTimeMs): self + { + $self = clone $this; + $self['inferenceTimeMs'] = $inferenceTimeMs; + + return $self; + } + + public function withInputTokens(float $inputTokens): self + { + $self = clone $this; + $self['inputTokens'] = $inputTokens; + + return $self; + } + + public function withOutputTokens(float $outputTokens): self + { + $self = clone $this; + $self['outputTokens'] = $outputTokens; + + return $self; + } + + public function withCachedInputTokens(float $cachedInputTokens): self + { + $self = clone $this; + $self['cachedInputTokens'] = $cachedInputTokens; + + return $self; + } + + public function withReasoningTokens(float $reasoningTokens): self + { + $self = clone $this; + $self['reasoningTokens'] = $reasoningTokens; + + return $self; + } +} diff --git a/src/Sessions/SessionExtractParams.php b/src/Sessions/SessionExtractParams.php index 84f4b5c..643418d 100644 --- a/src/Sessions/SessionExtractParams.php +++ b/src/Sessions/SessionExtractParams.php @@ -8,18 +8,26 @@ use Stagehand\Core\Concerns\SdkModel; use Stagehand\Core\Concerns\SdkParams; use Stagehand\Core\Contracts\BaseModel; +use Stagehand\Sessions\SessionExtractParams\Options; +use Stagehand\Sessions\SessionExtractParams\XLanguage; +use Stagehand\Sessions\SessionExtractParams\XStreamResponse; /** * Extracts structured data from the current page using AI-powered analysis. * * @see Stagehand\Services\SessionsService::extract() * + * @phpstan-import-type OptionsShape from \Stagehand\Sessions\SessionExtractParams\Options + * * @phpstan-type SessionExtractParamsShape = array{ - * body?: mixed, - * xLanguage?: mixed, - * xSDKVersion?: mixed, - * xSentAt?: mixed, - * xStreamResponse?: mixed, + * frameID?: string|null, + * instruction?: string|null, + * options?: OptionsShape|null, + * schema?: array|null, + * xLanguage?: null|XLanguage|value-of, + * xSDKVersion?: string|null, + * xSentAt?: \DateTimeInterface|null, + * xStreamResponse?: null|XStreamResponse|value-of, * } */ final class SessionExtractParams implements BaseModel @@ -28,20 +36,56 @@ final class SessionExtractParams implements BaseModel use SdkModel; use SdkParams; - #[Optional] - public mixed $body; + /** + * Target frame ID for the extraction. + */ + #[Optional('frameId')] + public ?string $frameID; + /** + * Natural language instruction for what to extract. + */ #[Optional] - public mixed $xLanguage; + public ?string $instruction; #[Optional] - public mixed $xSDKVersion; + public ?Options $options; + + /** + * JSON Schema defining the structure of data to extract. + * + * @var array|null $schema + */ + #[Optional(map: 'mixed')] + public ?array $schema; + + /** + * Client SDK language. + * + * @var value-of|null $xLanguage + */ + #[Optional(enum: XLanguage::class)] + public ?string $xLanguage; + /** + * Version of the Stagehand SDK. + */ #[Optional] - public mixed $xSentAt; + public ?string $xSDKVersion; + /** + * ISO timestamp when request was sent. + */ #[Optional] - public mixed $xStreamResponse; + public ?\DateTimeInterface $xSentAt; + + /** + * Whether to stream the response via SSE. + * + * @var value-of|null $xStreamResponse + */ + #[Optional(enum: XStreamResponse::class)] + public ?string $xStreamResponse; public function __construct() { @@ -52,17 +96,28 @@ public function __construct() * Construct an instance from the required parameters. * * You must use named parameters to construct any parameters with a default value. + * + * @param OptionsShape $options + * @param array $schema + * @param XLanguage|value-of $xLanguage + * @param XStreamResponse|value-of $xStreamResponse */ public static function with( - mixed $body = null, - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, + ?string $frameID = null, + ?string $instruction = null, + Options|array|null $options = null, + ?array $schema = null, + XLanguage|string|null $xLanguage = null, + ?string $xSDKVersion = null, + ?\DateTimeInterface $xSentAt = null, + XStreamResponse|string|null $xStreamResponse = null, ): self { $self = new self; - null !== $body && $self['body'] = $body; + null !== $frameID && $self['frameID'] = $frameID; + null !== $instruction && $self['instruction'] = $instruction; + null !== $options && $self['options'] = $options; + null !== $schema && $self['schema'] = $schema; null !== $xLanguage && $self['xLanguage'] = $xLanguage; null !== $xSDKVersion && $self['xSDKVersion'] = $xSDKVersion; null !== $xSentAt && $self['xSentAt'] = $xSentAt; @@ -71,15 +126,58 @@ public static function with( return $self; } - public function withBody(mixed $body): self + /** + * Target frame ID for the extraction. + */ + public function withFrameID(string $frameID): self + { + $self = clone $this; + $self['frameID'] = $frameID; + + return $self; + } + + /** + * Natural language instruction for what to extract. + */ + public function withInstruction(string $instruction): self + { + $self = clone $this; + $self['instruction'] = $instruction; + + return $self; + } + + /** + * @param OptionsShape $options + */ + public function withOptions(Options|array $options): self { $self = clone $this; - $self['body'] = $body; + $self['options'] = $options; return $self; } - public function withXLanguage(mixed $xLanguage): self + /** + * JSON Schema defining the structure of data to extract. + * + * @param array $schema + */ + public function withSchema(array $schema): self + { + $self = clone $this; + $self['schema'] = $schema; + + return $self; + } + + /** + * Client SDK language. + * + * @param XLanguage|value-of $xLanguage + */ + public function withXLanguage(XLanguage|string $xLanguage): self { $self = clone $this; $self['xLanguage'] = $xLanguage; @@ -87,7 +185,10 @@ public function withXLanguage(mixed $xLanguage): self return $self; } - public function withXSDKVersion(mixed $xSDKVersion): self + /** + * Version of the Stagehand SDK. + */ + public function withXSDKVersion(string $xSDKVersion): self { $self = clone $this; $self['xSDKVersion'] = $xSDKVersion; @@ -95,7 +196,10 @@ public function withXSDKVersion(mixed $xSDKVersion): self return $self; } - public function withXSentAt(mixed $xSentAt): self + /** + * ISO timestamp when request was sent. + */ + public function withXSentAt(\DateTimeInterface $xSentAt): self { $self = clone $this; $self['xSentAt'] = $xSentAt; @@ -103,8 +207,14 @@ public function withXSentAt(mixed $xSentAt): self return $self; } - public function withXStreamResponse(mixed $xStreamResponse): self - { + /** + * Whether to stream the response via SSE. + * + * @param XStreamResponse|value-of $xStreamResponse + */ + public function withXStreamResponse( + XStreamResponse|string $xStreamResponse + ): self { $self = clone $this; $self['xStreamResponse'] = $xStreamResponse; diff --git a/src/Sessions/SessionExtractParams/Options.php b/src/Sessions/SessionExtractParams/Options.php new file mode 100644 index 0000000..b437deb --- /dev/null +++ b/src/Sessions/SessionExtractParams/Options.php @@ -0,0 +1,97 @@ + */ + use SdkModel; + + #[Optional] + public string|UnionMember1|null $model; + + /** + * CSS selector to scope extraction to a specific element. + */ + #[Optional] + public ?string $selector; + + /** + * Timeout in ms for the extraction. + */ + #[Optional] + public ?float $timeout; + + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param ModelConfigShape $model + */ + public static function with( + string|UnionMember1|array|null $model = null, + ?string $selector = null, + ?float $timeout = null, + ): self { + $self = new self; + + null !== $model && $self['model'] = $model; + null !== $selector && $self['selector'] = $selector; + null !== $timeout && $self['timeout'] = $timeout; + + return $self; + } + + /** + * @param ModelConfigShape $model + */ + public function withModel(string|UnionMember1|array $model): self + { + $self = clone $this; + $self['model'] = $model; + + return $self; + } + + /** + * CSS selector to scope extraction to a specific element. + */ + public function withSelector(string $selector): self + { + $self = clone $this; + $self['selector'] = $selector; + + return $self; + } + + /** + * Timeout in ms for the extraction. + */ + public function withTimeout(float $timeout): self + { + $self = clone $this; + $self['timeout'] = $timeout; + + return $self; + } +} diff --git a/src/Sessions/SessionExtractParams/XLanguage.php b/src/Sessions/SessionExtractParams/XLanguage.php new file mode 100644 index 0000000..677e218 --- /dev/null +++ b/src/Sessions/SessionExtractParams/XLanguage.php @@ -0,0 +1,17 @@ + */ + use SdkModel; + + #[Required] + public Data $data; + + #[Required] + public bool $success; + + /** + * `new SessionExtractResponse()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * SessionExtractResponse::with(data: ..., success: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new SessionExtractResponse)->withData(...)->withSuccess(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param DataShape $data + */ + public static function with(Data|array $data, bool $success): self + { + $self = new self; + + $self['data'] = $data; + $self['success'] = $success; + + return $self; + } + + /** + * @param DataShape $data + */ + public function withData(Data|array $data): self + { + $self = clone $this; + $self['data'] = $data; + + return $self; + } + + public function withSuccess(bool $success): self + { + $self = clone $this; + $self['success'] = $success; + + return $self; + } +} diff --git a/src/Sessions/SessionExtractResponse/Data.php b/src/Sessions/SessionExtractResponse/Data.php new file mode 100644 index 0000000..e80c821 --- /dev/null +++ b/src/Sessions/SessionExtractResponse/Data.php @@ -0,0 +1,88 @@ + */ + use SdkModel; + + /** + * Extracted data matching the requested schema. + */ + #[Required] + public mixed $result; + + /** + * Action ID for tracking. + */ + #[Optional('actionId')] + public ?string $actionID; + + /** + * `new Data()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * Data::with(result: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new Data)->withResult(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with(mixed $result, ?string $actionID = null): self + { + $self = new self; + + $self['result'] = $result; + + null !== $actionID && $self['actionID'] = $actionID; + + return $self; + } + + /** + * Extracted data matching the requested schema. + */ + public function withResult(mixed $result): self + { + $self = clone $this; + $self['result'] = $result; + + return $self; + } + + /** + * Action ID for tracking. + */ + public function withActionID(string $actionID): self + { + $self = clone $this; + $self['actionID'] = $actionID; + + return $self; + } +} diff --git a/src/Sessions/SessionNavigateParams.php b/src/Sessions/SessionNavigateParams.php index 0bf0197..ccfdbe5 100644 --- a/src/Sessions/SessionNavigateParams.php +++ b/src/Sessions/SessionNavigateParams.php @@ -5,21 +5,29 @@ namespace Stagehand\Sessions; use Stagehand\Core\Attributes\Optional; +use Stagehand\Core\Attributes\Required; use Stagehand\Core\Concerns\SdkModel; use Stagehand\Core\Concerns\SdkParams; use Stagehand\Core\Contracts\BaseModel; +use Stagehand\Sessions\SessionNavigateParams\Options; +use Stagehand\Sessions\SessionNavigateParams\XLanguage; +use Stagehand\Sessions\SessionNavigateParams\XStreamResponse; /** * Navigates the browser to the specified URL. * * @see Stagehand\Services\SessionsService::navigate() * + * @phpstan-import-type OptionsShape from \Stagehand\Sessions\SessionNavigateParams\Options + * * @phpstan-type SessionNavigateParamsShape = array{ - * body?: mixed, - * xLanguage?: mixed, - * xSDKVersion?: mixed, - * xSentAt?: mixed, - * xStreamResponse?: mixed, + * url: string, + * frameID?: string|null, + * options?: OptionsShape|null, + * xLanguage?: null|XLanguage|value-of, + * xSDKVersion?: string|null, + * xSentAt?: \DateTimeInterface|null, + * xStreamResponse?: null|XStreamResponse|value-of, * } */ final class SessionNavigateParams implements BaseModel @@ -28,21 +36,63 @@ final class SessionNavigateParams implements BaseModel use SdkModel; use SdkParams; - #[Optional] - public mixed $body; + /** + * URL to navigate to. + */ + #[Required] + public string $url; - #[Optional] - public mixed $xLanguage; + /** + * Target frame ID for the navigation. + */ + #[Optional('frameId')] + public ?string $frameID; #[Optional] - public mixed $xSDKVersion; + public ?Options $options; + /** + * Client SDK language. + * + * @var value-of|null $xLanguage + */ + #[Optional(enum: XLanguage::class)] + public ?string $xLanguage; + + /** + * Version of the Stagehand SDK. + */ #[Optional] - public mixed $xSentAt; + public ?string $xSDKVersion; + /** + * ISO timestamp when request was sent. + */ #[Optional] - public mixed $xStreamResponse; + public ?\DateTimeInterface $xSentAt; + /** + * Whether to stream the response via SSE. + * + * @var value-of|null $xStreamResponse + */ + #[Optional(enum: XStreamResponse::class)] + public ?string $xStreamResponse; + + /** + * `new SessionNavigateParams()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * SessionNavigateParams::with(url: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new SessionNavigateParams)->withURL(...) + * ``` + */ public function __construct() { $this->initialize(); @@ -52,17 +102,26 @@ public function __construct() * Construct an instance from the required parameters. * * You must use named parameters to construct any parameters with a default value. + * + * @param OptionsShape $options + * @param XLanguage|value-of $xLanguage + * @param XStreamResponse|value-of $xStreamResponse */ public static function with( - mixed $body = null, - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, + string $url, + ?string $frameID = null, + Options|array|null $options = null, + XLanguage|string|null $xLanguage = null, + ?string $xSDKVersion = null, + ?\DateTimeInterface $xSentAt = null, + XStreamResponse|string|null $xStreamResponse = null, ): self { $self = new self; - null !== $body && $self['body'] = $body; + $self['url'] = $url; + + null !== $frameID && $self['frameID'] = $frameID; + null !== $options && $self['options'] = $options; null !== $xLanguage && $self['xLanguage'] = $xLanguage; null !== $xSDKVersion && $self['xSDKVersion'] = $xSDKVersion; null !== $xSentAt && $self['xSentAt'] = $xSentAt; @@ -71,15 +130,45 @@ public static function with( return $self; } - public function withBody(mixed $body): self + /** + * URL to navigate to. + */ + public function withURL(string $url): self + { + $self = clone $this; + $self['url'] = $url; + + return $self; + } + + /** + * Target frame ID for the navigation. + */ + public function withFrameID(string $frameID): self + { + $self = clone $this; + $self['frameID'] = $frameID; + + return $self; + } + + /** + * @param OptionsShape $options + */ + public function withOptions(Options|array $options): self { $self = clone $this; - $self['body'] = $body; + $self['options'] = $options; return $self; } - public function withXLanguage(mixed $xLanguage): self + /** + * Client SDK language. + * + * @param XLanguage|value-of $xLanguage + */ + public function withXLanguage(XLanguage|string $xLanguage): self { $self = clone $this; $self['xLanguage'] = $xLanguage; @@ -87,7 +176,10 @@ public function withXLanguage(mixed $xLanguage): self return $self; } - public function withXSDKVersion(mixed $xSDKVersion): self + /** + * Version of the Stagehand SDK. + */ + public function withXSDKVersion(string $xSDKVersion): self { $self = clone $this; $self['xSDKVersion'] = $xSDKVersion; @@ -95,7 +187,10 @@ public function withXSDKVersion(mixed $xSDKVersion): self return $self; } - public function withXSentAt(mixed $xSentAt): self + /** + * ISO timestamp when request was sent. + */ + public function withXSentAt(\DateTimeInterface $xSentAt): self { $self = clone $this; $self['xSentAt'] = $xSentAt; @@ -103,8 +198,14 @@ public function withXSentAt(mixed $xSentAt): self return $self; } - public function withXStreamResponse(mixed $xStreamResponse): self - { + /** + * Whether to stream the response via SSE. + * + * @param XStreamResponse|value-of $xStreamResponse + */ + public function withXStreamResponse( + XStreamResponse|string $xStreamResponse + ): self { $self = clone $this; $self['xStreamResponse'] = $xStreamResponse; diff --git a/src/Sessions/SessionNavigateParams/Options.php b/src/Sessions/SessionNavigateParams/Options.php new file mode 100644 index 0000000..a94861c --- /dev/null +++ b/src/Sessions/SessionNavigateParams/Options.php @@ -0,0 +1,104 @@ +, + * } + */ +final class Options implements BaseModel +{ + /** @use SdkModel */ + use SdkModel; + + /** + * Referer header to send with the request. + */ + #[Optional] + public ?string $referer; + + /** + * Timeout in ms for the navigation. + */ + #[Optional] + public ?float $timeout; + + /** + * When to consider navigation complete. + * + * @var value-of|null $waitUntil + */ + #[Optional(enum: WaitUntil::class)] + public ?string $waitUntil; + + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param WaitUntil|value-of $waitUntil + */ + public static function with( + ?string $referer = null, + ?float $timeout = null, + WaitUntil|string|null $waitUntil = null, + ): self { + $self = new self; + + null !== $referer && $self['referer'] = $referer; + null !== $timeout && $self['timeout'] = $timeout; + null !== $waitUntil && $self['waitUntil'] = $waitUntil; + + return $self; + } + + /** + * Referer header to send with the request. + */ + public function withReferer(string $referer): self + { + $self = clone $this; + $self['referer'] = $referer; + + return $self; + } + + /** + * Timeout in ms for the navigation. + */ + public function withTimeout(float $timeout): self + { + $self = clone $this; + $self['timeout'] = $timeout; + + return $self; + } + + /** + * When to consider navigation complete. + * + * @param WaitUntil|value-of $waitUntil + */ + public function withWaitUntil(WaitUntil|string $waitUntil): self + { + $self = clone $this; + $self['waitUntil'] = $waitUntil; + + return $self; + } +} diff --git a/src/Sessions/SessionNavigateParams/Options/WaitUntil.php b/src/Sessions/SessionNavigateParams/Options/WaitUntil.php new file mode 100644 index 0000000..2813cb1 --- /dev/null +++ b/src/Sessions/SessionNavigateParams/Options/WaitUntil.php @@ -0,0 +1,17 @@ + */ + use SdkModel; + + #[Required] + public Data $data; + + #[Required] + public bool $success; + + /** + * `new SessionNavigateResponse()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * SessionNavigateResponse::with(data: ..., success: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new SessionNavigateResponse)->withData(...)->withSuccess(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param DataShape $data + */ + public static function with(Data|array $data, bool $success): self + { + $self = new self; + + $self['data'] = $data; + $self['success'] = $success; + + return $self; + } + + /** + * @param DataShape $data + */ + public function withData(Data|array $data): self + { + $self = clone $this; + $self['data'] = $data; + + return $self; + } + + public function withSuccess(bool $success): self + { + $self = clone $this; + $self['success'] = $success; + + return $self; + } +} diff --git a/src/Sessions/SessionNavigateResponse/Data.php b/src/Sessions/SessionNavigateResponse/Data.php new file mode 100644 index 0000000..cf584bc --- /dev/null +++ b/src/Sessions/SessionNavigateResponse/Data.php @@ -0,0 +1,88 @@ + */ + use SdkModel; + + /** + * Navigation response (Playwright Response object or null). + */ + #[Required] + public mixed $result; + + /** + * Action ID for tracking. + */ + #[Optional('actionId')] + public ?string $actionID; + + /** + * `new Data()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * Data::with(result: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new Data)->withResult(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with(mixed $result, ?string $actionID = null): self + { + $self = new self; + + $self['result'] = $result; + + null !== $actionID && $self['actionID'] = $actionID; + + return $self; + } + + /** + * Navigation response (Playwright Response object or null). + */ + public function withResult(mixed $result): self + { + $self = clone $this; + $self['result'] = $result; + + return $self; + } + + /** + * Action ID for tracking. + */ + public function withActionID(string $actionID): self + { + $self = clone $this; + $self['actionID'] = $actionID; + + return $self; + } +} diff --git a/src/Sessions/SessionObserveParams.php b/src/Sessions/SessionObserveParams.php index 6f432c2..b9aba90 100644 --- a/src/Sessions/SessionObserveParams.php +++ b/src/Sessions/SessionObserveParams.php @@ -8,18 +8,25 @@ use Stagehand\Core\Concerns\SdkModel; use Stagehand\Core\Concerns\SdkParams; use Stagehand\Core\Contracts\BaseModel; +use Stagehand\Sessions\SessionObserveParams\Options; +use Stagehand\Sessions\SessionObserveParams\XLanguage; +use Stagehand\Sessions\SessionObserveParams\XStreamResponse; /** * Identifies and returns available actions on the current page that match the given instruction. * * @see Stagehand\Services\SessionsService::observe() * + * @phpstan-import-type OptionsShape from \Stagehand\Sessions\SessionObserveParams\Options + * * @phpstan-type SessionObserveParamsShape = array{ - * body?: mixed, - * xLanguage?: mixed, - * xSDKVersion?: mixed, - * xSentAt?: mixed, - * xStreamResponse?: mixed, + * frameID?: string|null, + * instruction?: string|null, + * options?: OptionsShape|null, + * xLanguage?: null|XLanguage|value-of, + * xSDKVersion?: string|null, + * xSentAt?: \DateTimeInterface|null, + * xStreamResponse?: null|XStreamResponse|value-of, * } */ final class SessionObserveParams implements BaseModel @@ -28,20 +35,48 @@ final class SessionObserveParams implements BaseModel use SdkModel; use SdkParams; - #[Optional] - public mixed $body; + /** + * Target frame ID for the observation. + */ + #[Optional('frameId')] + public ?string $frameID; + /** + * Natural language instruction for what actions to find. + */ #[Optional] - public mixed $xLanguage; + public ?string $instruction; #[Optional] - public mixed $xSDKVersion; + public ?Options $options; + /** + * Client SDK language. + * + * @var value-of|null $xLanguage + */ + #[Optional(enum: XLanguage::class)] + public ?string $xLanguage; + + /** + * Version of the Stagehand SDK. + */ #[Optional] - public mixed $xSentAt; + public ?string $xSDKVersion; + /** + * ISO timestamp when request was sent. + */ #[Optional] - public mixed $xStreamResponse; + public ?\DateTimeInterface $xSentAt; + + /** + * Whether to stream the response via SSE. + * + * @var value-of|null $xStreamResponse + */ + #[Optional(enum: XStreamResponse::class)] + public ?string $xStreamResponse; public function __construct() { @@ -52,17 +87,25 @@ public function __construct() * Construct an instance from the required parameters. * * You must use named parameters to construct any parameters with a default value. + * + * @param OptionsShape $options + * @param XLanguage|value-of $xLanguage + * @param XStreamResponse|value-of $xStreamResponse */ public static function with( - mixed $body = null, - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, + ?string $frameID = null, + ?string $instruction = null, + Options|array|null $options = null, + XLanguage|string|null $xLanguage = null, + ?string $xSDKVersion = null, + ?\DateTimeInterface $xSentAt = null, + XStreamResponse|string|null $xStreamResponse = null, ): self { $self = new self; - null !== $body && $self['body'] = $body; + null !== $frameID && $self['frameID'] = $frameID; + null !== $instruction && $self['instruction'] = $instruction; + null !== $options && $self['options'] = $options; null !== $xLanguage && $self['xLanguage'] = $xLanguage; null !== $xSDKVersion && $self['xSDKVersion'] = $xSDKVersion; null !== $xSentAt && $self['xSentAt'] = $xSentAt; @@ -71,15 +114,45 @@ public static function with( return $self; } - public function withBody(mixed $body): self + /** + * Target frame ID for the observation. + */ + public function withFrameID(string $frameID): self { $self = clone $this; - $self['body'] = $body; + $self['frameID'] = $frameID; return $self; } - public function withXLanguage(mixed $xLanguage): self + /** + * Natural language instruction for what actions to find. + */ + public function withInstruction(string $instruction): self + { + $self = clone $this; + $self['instruction'] = $instruction; + + return $self; + } + + /** + * @param OptionsShape $options + */ + public function withOptions(Options|array $options): self + { + $self = clone $this; + $self['options'] = $options; + + return $self; + } + + /** + * Client SDK language. + * + * @param XLanguage|value-of $xLanguage + */ + public function withXLanguage(XLanguage|string $xLanguage): self { $self = clone $this; $self['xLanguage'] = $xLanguage; @@ -87,7 +160,10 @@ public function withXLanguage(mixed $xLanguage): self return $self; } - public function withXSDKVersion(mixed $xSDKVersion): self + /** + * Version of the Stagehand SDK. + */ + public function withXSDKVersion(string $xSDKVersion): self { $self = clone $this; $self['xSDKVersion'] = $xSDKVersion; @@ -95,7 +171,10 @@ public function withXSDKVersion(mixed $xSDKVersion): self return $self; } - public function withXSentAt(mixed $xSentAt): self + /** + * ISO timestamp when request was sent. + */ + public function withXSentAt(\DateTimeInterface $xSentAt): self { $self = clone $this; $self['xSentAt'] = $xSentAt; @@ -103,8 +182,14 @@ public function withXSentAt(mixed $xSentAt): self return $self; } - public function withXStreamResponse(mixed $xStreamResponse): self - { + /** + * Whether to stream the response via SSE. + * + * @param XStreamResponse|value-of $xStreamResponse + */ + public function withXStreamResponse( + XStreamResponse|string $xStreamResponse + ): self { $self = clone $this; $self['xStreamResponse'] = $xStreamResponse; diff --git a/src/Sessions/SessionObserveParams/Options.php b/src/Sessions/SessionObserveParams/Options.php new file mode 100644 index 0000000..767953c --- /dev/null +++ b/src/Sessions/SessionObserveParams/Options.php @@ -0,0 +1,97 @@ + */ + use SdkModel; + + #[Optional] + public string|UnionMember1|null $model; + + /** + * CSS selector to scope observation to a specific element. + */ + #[Optional] + public ?string $selector; + + /** + * Timeout in ms for the observation. + */ + #[Optional] + public ?float $timeout; + + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param ModelConfigShape $model + */ + public static function with( + string|UnionMember1|array|null $model = null, + ?string $selector = null, + ?float $timeout = null, + ): self { + $self = new self; + + null !== $model && $self['model'] = $model; + null !== $selector && $self['selector'] = $selector; + null !== $timeout && $self['timeout'] = $timeout; + + return $self; + } + + /** + * @param ModelConfigShape $model + */ + public function withModel(string|UnionMember1|array $model): self + { + $self = clone $this; + $self['model'] = $model; + + return $self; + } + + /** + * CSS selector to scope observation to a specific element. + */ + public function withSelector(string $selector): self + { + $self = clone $this; + $self['selector'] = $selector; + + return $self; + } + + /** + * Timeout in ms for the observation. + */ + public function withTimeout(float $timeout): self + { + $self = clone $this; + $self['timeout'] = $timeout; + + return $self; + } +} diff --git a/src/Sessions/SessionObserveParams/XLanguage.php b/src/Sessions/SessionObserveParams/XLanguage.php new file mode 100644 index 0000000..a6afb44 --- /dev/null +++ b/src/Sessions/SessionObserveParams/XLanguage.php @@ -0,0 +1,17 @@ + */ + use SdkModel; + + #[Required] + public Data $data; + + #[Required] + public bool $success; + + /** + * `new SessionObserveResponse()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * SessionObserveResponse::with(data: ..., success: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new SessionObserveResponse)->withData(...)->withSuccess(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param DataShape $data + */ + public static function with(Data|array $data, bool $success): self + { + $self = new self; + + $self['data'] = $data; + $self['success'] = $success; + + return $self; + } + + /** + * @param DataShape $data + */ + public function withData(Data|array $data): self + { + $self = clone $this; + $self['data'] = $data; + + return $self; + } + + public function withSuccess(bool $success): self + { + $self = clone $this; + $self['success'] = $success; + + return $self; + } +} diff --git a/src/Sessions/SessionObserveResponse/Data.php b/src/Sessions/SessionObserveResponse/Data.php new file mode 100644 index 0000000..cbf6aa3 --- /dev/null +++ b/src/Sessions/SessionObserveResponse/Data.php @@ -0,0 +1,93 @@ +, actionID?: string|null + * } + */ +final class Data implements BaseModel +{ + /** @use SdkModel */ + use SdkModel; + + /** @var list $result */ + #[Required(list: Action::class)] + public array $result; + + /** + * Action ID for tracking. + */ + #[Optional('actionId')] + public ?string $actionID; + + /** + * `new Data()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * Data::with(result: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new Data)->withResult(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param list $result + */ + public static function with(array $result, ?string $actionID = null): self + { + $self = new self; + + $self['result'] = $result; + + null !== $actionID && $self['actionID'] = $actionID; + + return $self; + } + + /** + * @param list $result + */ + public function withResult(array $result): self + { + $self = clone $this; + $self['result'] = $result; + + return $self; + } + + /** + * Action ID for tracking. + */ + public function withActionID(string $actionID): self + { + $self = clone $this; + $self['actionID'] = $actionID; + + return $self; + } +} diff --git a/src/Sessions/SessionStartParams.php b/src/Sessions/SessionStartParams.php index 499f592..79c3fce 100644 --- a/src/Sessions/SessionStartParams.php +++ b/src/Sessions/SessionStartParams.php @@ -5,21 +5,40 @@ namespace Stagehand\Sessions; use Stagehand\Core\Attributes\Optional; +use Stagehand\Core\Attributes\Required; use Stagehand\Core\Concerns\SdkModel; use Stagehand\Core\Concerns\SdkParams; use Stagehand\Core\Contracts\BaseModel; +use Stagehand\Sessions\SessionStartParams\Browser; +use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams; +use Stagehand\Sessions\SessionStartParams\XLanguage; +use Stagehand\Sessions\SessionStartParams\XStreamResponse; /** * Creates a new browser session with the specified configuration. Returns a session ID used for all subsequent operations. * * @see Stagehand\Services\SessionsService::start() * + * @phpstan-import-type BrowserShape from \Stagehand\Sessions\SessionStartParams\Browser + * @phpstan-import-type BrowserbaseSessionCreateParamsShape from \Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams + * * @phpstan-type SessionStartParamsShape = array{ - * body?: mixed, - * xLanguage?: mixed, - * xSDKVersion?: mixed, - * xSentAt?: mixed, - * xStreamResponse?: mixed, + * modelName: string, + * actTimeoutMs?: float|null, + * browser?: BrowserShape|null, + * browserbaseSessionCreateParams?: BrowserbaseSessionCreateParamsShape|null, + * browserbaseSessionID?: string|null, + * debugDom?: bool|null, + * domSettleTimeoutMs?: float|null, + * experimental?: bool|null, + * selfHeal?: bool|null, + * systemPrompt?: string|null, + * verbose?: float|null, + * waitForCaptchaSolves?: bool|null, + * xLanguage?: null|XLanguage|value-of, + * xSDKVersion?: string|null, + * xSentAt?: \DateTimeInterface|null, + * xStreamResponse?: null|XStreamResponse|value-of, * } */ final class SessionStartParams implements BaseModel @@ -28,21 +47,105 @@ final class SessionStartParams implements BaseModel use SdkModel; use SdkParams; + /** + * Model name to use for AI operations. + */ + #[Required] + public string $modelName; + + /** + * Timeout in ms for act operations. + */ + #[Optional] + public ?float $actTimeoutMs; + #[Optional] - public mixed $body; + public ?Browser $browser; #[Optional] - public mixed $xLanguage; + public ?BrowserbaseSessionCreateParams $browserbaseSessionCreateParams; + /** + * Existing Browserbase session ID to resume. + */ #[Optional] - public mixed $xSDKVersion; + public ?string $browserbaseSessionID; #[Optional] - public mixed $xSentAt; + public ?bool $debugDom; + + /** + * Timeout in ms to wait for DOM to settle. + */ + #[Optional] + public ?float $domSettleTimeoutMs; + + #[Optional] + public ?bool $experimental; + + /** + * Enable self-healing for failed actions. + */ + #[Optional] + public ?bool $selfHeal; + + /** + * Custom system prompt for AI operations. + */ + #[Optional] + public ?string $systemPrompt; + + /** + * Logging verbosity level (0=quiet, 1=normal, 2=debug). + */ + #[Optional] + public ?float $verbose; + + #[Optional] + public ?bool $waitForCaptchaSolves; + + /** + * Client SDK language. + * + * @var value-of|null $xLanguage + */ + #[Optional(enum: XLanguage::class)] + public ?string $xLanguage; + + /** + * Version of the Stagehand SDK. + */ + #[Optional] + public ?string $xSDKVersion; + /** + * ISO timestamp when request was sent. + */ #[Optional] - public mixed $xStreamResponse; + public ?\DateTimeInterface $xSentAt; + + /** + * Whether to stream the response via SSE. + * + * @var value-of|null $xStreamResponse + */ + #[Optional(enum: XStreamResponse::class)] + public ?string $xStreamResponse; + /** + * `new SessionStartParams()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * SessionStartParams::with(modelName: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new SessionStartParams)->withModelName(...) + * ``` + */ public function __construct() { $this->initialize(); @@ -52,17 +155,45 @@ public function __construct() * Construct an instance from the required parameters. * * You must use named parameters to construct any parameters with a default value. + * + * @param BrowserShape $browser + * @param BrowserbaseSessionCreateParamsShape $browserbaseSessionCreateParams + * @param XLanguage|value-of $xLanguage + * @param XStreamResponse|value-of $xStreamResponse */ public static function with( - mixed $body = null, - mixed $xLanguage = null, - mixed $xSDKVersion = null, - mixed $xSentAt = null, - mixed $xStreamResponse = null, + string $modelName, + ?float $actTimeoutMs = null, + Browser|array|null $browser = null, + BrowserbaseSessionCreateParams|array|null $browserbaseSessionCreateParams = null, + ?string $browserbaseSessionID = null, + ?bool $debugDom = null, + ?float $domSettleTimeoutMs = null, + ?bool $experimental = null, + ?bool $selfHeal = null, + ?string $systemPrompt = null, + ?float $verbose = null, + ?bool $waitForCaptchaSolves = null, + XLanguage|string|null $xLanguage = null, + ?string $xSDKVersion = null, + ?\DateTimeInterface $xSentAt = null, + XStreamResponse|string|null $xStreamResponse = null, ): self { $self = new self; - null !== $body && $self['body'] = $body; + $self['modelName'] = $modelName; + + null !== $actTimeoutMs && $self['actTimeoutMs'] = $actTimeoutMs; + null !== $browser && $self['browser'] = $browser; + null !== $browserbaseSessionCreateParams && $self['browserbaseSessionCreateParams'] = $browserbaseSessionCreateParams; + null !== $browserbaseSessionID && $self['browserbaseSessionID'] = $browserbaseSessionID; + null !== $debugDom && $self['debugDom'] = $debugDom; + null !== $domSettleTimeoutMs && $self['domSettleTimeoutMs'] = $domSettleTimeoutMs; + null !== $experimental && $self['experimental'] = $experimental; + null !== $selfHeal && $self['selfHeal'] = $selfHeal; + null !== $systemPrompt && $self['systemPrompt'] = $systemPrompt; + null !== $verbose && $self['verbose'] = $verbose; + null !== $waitForCaptchaSolves && $self['waitForCaptchaSolves'] = $waitForCaptchaSolves; null !== $xLanguage && $self['xLanguage'] = $xLanguage; null !== $xSDKVersion && $self['xSDKVersion'] = $xSDKVersion; null !== $xSentAt && $self['xSentAt'] = $xSentAt; @@ -71,15 +202,136 @@ public static function with( return $self; } - public function withBody(mixed $body): self + /** + * Model name to use for AI operations. + */ + public function withModelName(string $modelName): self { $self = clone $this; - $self['body'] = $body; + $self['modelName'] = $modelName; return $self; } - public function withXLanguage(mixed $xLanguage): self + /** + * Timeout in ms for act operations. + */ + public function withActTimeoutMs(float $actTimeoutMs): self + { + $self = clone $this; + $self['actTimeoutMs'] = $actTimeoutMs; + + return $self; + } + + /** + * @param BrowserShape $browser + */ + public function withBrowser(Browser|array $browser): self + { + $self = clone $this; + $self['browser'] = $browser; + + return $self; + } + + /** + * @param BrowserbaseSessionCreateParamsShape $browserbaseSessionCreateParams + */ + public function withBrowserbaseSessionCreateParams( + BrowserbaseSessionCreateParams|array $browserbaseSessionCreateParams + ): self { + $self = clone $this; + $self['browserbaseSessionCreateParams'] = $browserbaseSessionCreateParams; + + return $self; + } + + /** + * Existing Browserbase session ID to resume. + */ + public function withBrowserbaseSessionID(string $browserbaseSessionID): self + { + $self = clone $this; + $self['browserbaseSessionID'] = $browserbaseSessionID; + + return $self; + } + + public function withDebugDom(bool $debugDom): self + { + $self = clone $this; + $self['debugDom'] = $debugDom; + + return $self; + } + + /** + * Timeout in ms to wait for DOM to settle. + */ + public function withDomSettleTimeoutMs(float $domSettleTimeoutMs): self + { + $self = clone $this; + $self['domSettleTimeoutMs'] = $domSettleTimeoutMs; + + return $self; + } + + public function withExperimental(bool $experimental): self + { + $self = clone $this; + $self['experimental'] = $experimental; + + return $self; + } + + /** + * Enable self-healing for failed actions. + */ + public function withSelfHeal(bool $selfHeal): self + { + $self = clone $this; + $self['selfHeal'] = $selfHeal; + + return $self; + } + + /** + * Custom system prompt for AI operations. + */ + public function withSystemPrompt(string $systemPrompt): self + { + $self = clone $this; + $self['systemPrompt'] = $systemPrompt; + + return $self; + } + + /** + * Logging verbosity level (0=quiet, 1=normal, 2=debug). + */ + public function withVerbose(float $verbose): self + { + $self = clone $this; + $self['verbose'] = $verbose; + + return $self; + } + + public function withWaitForCaptchaSolves(bool $waitForCaptchaSolves): self + { + $self = clone $this; + $self['waitForCaptchaSolves'] = $waitForCaptchaSolves; + + return $self; + } + + /** + * Client SDK language. + * + * @param XLanguage|value-of $xLanguage + */ + public function withXLanguage(XLanguage|string $xLanguage): self { $self = clone $this; $self['xLanguage'] = $xLanguage; @@ -87,7 +339,10 @@ public function withXLanguage(mixed $xLanguage): self return $self; } - public function withXSDKVersion(mixed $xSDKVersion): self + /** + * Version of the Stagehand SDK. + */ + public function withXSDKVersion(string $xSDKVersion): self { $self = clone $this; $self['xSDKVersion'] = $xSDKVersion; @@ -95,7 +350,10 @@ public function withXSDKVersion(mixed $xSDKVersion): self return $self; } - public function withXSentAt(mixed $xSentAt): self + /** + * ISO timestamp when request was sent. + */ + public function withXSentAt(\DateTimeInterface $xSentAt): self { $self = clone $this; $self['xSentAt'] = $xSentAt; @@ -103,8 +361,14 @@ public function withXSentAt(mixed $xSentAt): self return $self; } - public function withXStreamResponse(mixed $xStreamResponse): self - { + /** + * Whether to stream the response via SSE. + * + * @param XStreamResponse|value-of $xStreamResponse + */ + public function withXStreamResponse( + XStreamResponse|string $xStreamResponse + ): self { $self = clone $this; $self['xStreamResponse'] = $xStreamResponse; diff --git a/src/Sessions/SessionStartParams/Browser.php b/src/Sessions/SessionStartParams/Browser.php new file mode 100644 index 0000000..90c9bd4 --- /dev/null +++ b/src/Sessions/SessionStartParams/Browser.php @@ -0,0 +1,105 @@ +, + * } + */ +final class Browser implements BaseModel +{ + /** @use SdkModel */ + use SdkModel; + + /** + * Chrome DevTools Protocol URL for connecting to existing browser. + */ + #[Optional('cdpUrl')] + public ?string $cdpURL; + + #[Optional] + public ?LaunchOptions $launchOptions; + + /** + * Browser type to use. + * + * @var value-of|null $type + */ + #[Optional(enum: Type::class)] + public ?string $type; + + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param LaunchOptionsShape $launchOptions + * @param Type|value-of $type + */ + public static function with( + ?string $cdpURL = null, + LaunchOptions|array|null $launchOptions = null, + Type|string|null $type = null, + ): self { + $self = new self; + + null !== $cdpURL && $self['cdpURL'] = $cdpURL; + null !== $launchOptions && $self['launchOptions'] = $launchOptions; + null !== $type && $self['type'] = $type; + + return $self; + } + + /** + * Chrome DevTools Protocol URL for connecting to existing browser. + */ + public function withCdpURL(string $cdpURL): self + { + $self = clone $this; + $self['cdpURL'] = $cdpURL; + + return $self; + } + + /** + * @param LaunchOptionsShape $launchOptions + */ + public function withLaunchOptions(LaunchOptions|array $launchOptions): self + { + $self = clone $this; + $self['launchOptions'] = $launchOptions; + + return $self; + } + + /** + * Browser type to use. + * + * @param Type|value-of $type + */ + public function withType(Type|string $type): self + { + $self = clone $this; + $self['type'] = $type; + + return $self; + } +} diff --git a/src/Sessions/SessionStartParams/Browser/LaunchOptions.php b/src/Sessions/SessionStartParams/Browser/LaunchOptions.php new file mode 100644 index 0000000..292c049 --- /dev/null +++ b/src/Sessions/SessionStartParams/Browser/LaunchOptions.php @@ -0,0 +1,315 @@ +|null, + * cdpURL?: string|null, + * chromiumSandbox?: bool|null, + * connectTimeoutMs?: float|null, + * deviceScaleFactor?: float|null, + * devtools?: bool|null, + * downloadsPath?: string|null, + * executablePath?: string|null, + * hasTouch?: bool|null, + * headless?: bool|null, + * ignoreDefaultArgs?: IgnoreDefaultArgsShape|null, + * ignoreHTTPSErrors?: bool|null, + * locale?: string|null, + * preserveUserDataDir?: bool|null, + * proxy?: null|Proxy|ProxyShape, + * userDataDir?: string|null, + * viewport?: null|Viewport|ViewportShape, + * } + */ +final class LaunchOptions implements BaseModel +{ + /** @use SdkModel */ + use SdkModel; + + #[Optional] + public ?bool $acceptDownloads; + + /** @var list|null $args */ + #[Optional(list: 'string')] + public ?array $args; + + #[Optional('cdpUrl')] + public ?string $cdpURL; + + #[Optional] + public ?bool $chromiumSandbox; + + #[Optional] + public ?float $connectTimeoutMs; + + #[Optional] + public ?float $deviceScaleFactor; + + #[Optional] + public ?bool $devtools; + + #[Optional] + public ?string $downloadsPath; + + #[Optional] + public ?string $executablePath; + + #[Optional] + public ?bool $hasTouch; + + #[Optional] + public ?bool $headless; + + /** @var bool|list|null $ignoreDefaultArgs */ + #[Optional(union: IgnoreDefaultArgs::class)] + public bool|array|null $ignoreDefaultArgs; + + #[Optional] + public ?bool $ignoreHTTPSErrors; + + #[Optional] + public ?string $locale; + + #[Optional] + public ?bool $preserveUserDataDir; + + #[Optional] + public ?Proxy $proxy; + + #[Optional] + public ?string $userDataDir; + + #[Optional] + public ?Viewport $viewport; + + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param list $args + * @param IgnoreDefaultArgsShape $ignoreDefaultArgs + * @param ProxyShape $proxy + * @param ViewportShape $viewport + */ + public static function with( + ?bool $acceptDownloads = null, + ?array $args = null, + ?string $cdpURL = null, + ?bool $chromiumSandbox = null, + ?float $connectTimeoutMs = null, + ?float $deviceScaleFactor = null, + ?bool $devtools = null, + ?string $downloadsPath = null, + ?string $executablePath = null, + ?bool $hasTouch = null, + ?bool $headless = null, + bool|array|null $ignoreDefaultArgs = null, + ?bool $ignoreHTTPSErrors = null, + ?string $locale = null, + ?bool $preserveUserDataDir = null, + Proxy|array|null $proxy = null, + ?string $userDataDir = null, + Viewport|array|null $viewport = null, + ): self { + $self = new self; + + null !== $acceptDownloads && $self['acceptDownloads'] = $acceptDownloads; + null !== $args && $self['args'] = $args; + null !== $cdpURL && $self['cdpURL'] = $cdpURL; + null !== $chromiumSandbox && $self['chromiumSandbox'] = $chromiumSandbox; + null !== $connectTimeoutMs && $self['connectTimeoutMs'] = $connectTimeoutMs; + null !== $deviceScaleFactor && $self['deviceScaleFactor'] = $deviceScaleFactor; + null !== $devtools && $self['devtools'] = $devtools; + null !== $downloadsPath && $self['downloadsPath'] = $downloadsPath; + null !== $executablePath && $self['executablePath'] = $executablePath; + null !== $hasTouch && $self['hasTouch'] = $hasTouch; + null !== $headless && $self['headless'] = $headless; + null !== $ignoreDefaultArgs && $self['ignoreDefaultArgs'] = $ignoreDefaultArgs; + null !== $ignoreHTTPSErrors && $self['ignoreHTTPSErrors'] = $ignoreHTTPSErrors; + null !== $locale && $self['locale'] = $locale; + null !== $preserveUserDataDir && $self['preserveUserDataDir'] = $preserveUserDataDir; + null !== $proxy && $self['proxy'] = $proxy; + null !== $userDataDir && $self['userDataDir'] = $userDataDir; + null !== $viewport && $self['viewport'] = $viewport; + + return $self; + } + + public function withAcceptDownloads(bool $acceptDownloads): self + { + $self = clone $this; + $self['acceptDownloads'] = $acceptDownloads; + + return $self; + } + + /** + * @param list $args + */ + public function withArgs(array $args): self + { + $self = clone $this; + $self['args'] = $args; + + return $self; + } + + public function withCdpURL(string $cdpURL): self + { + $self = clone $this; + $self['cdpURL'] = $cdpURL; + + return $self; + } + + public function withChromiumSandbox(bool $chromiumSandbox): self + { + $self = clone $this; + $self['chromiumSandbox'] = $chromiumSandbox; + + return $self; + } + + public function withConnectTimeoutMs(float $connectTimeoutMs): self + { + $self = clone $this; + $self['connectTimeoutMs'] = $connectTimeoutMs; + + return $self; + } + + public function withDeviceScaleFactor(float $deviceScaleFactor): self + { + $self = clone $this; + $self['deviceScaleFactor'] = $deviceScaleFactor; + + return $self; + } + + public function withDevtools(bool $devtools): self + { + $self = clone $this; + $self['devtools'] = $devtools; + + return $self; + } + + public function withDownloadsPath(string $downloadsPath): self + { + $self = clone $this; + $self['downloadsPath'] = $downloadsPath; + + return $self; + } + + public function withExecutablePath(string $executablePath): self + { + $self = clone $this; + $self['executablePath'] = $executablePath; + + return $self; + } + + public function withHasTouch(bool $hasTouch): self + { + $self = clone $this; + $self['hasTouch'] = $hasTouch; + + return $self; + } + + public function withHeadless(bool $headless): self + { + $self = clone $this; + $self['headless'] = $headless; + + return $self; + } + + /** + * @param IgnoreDefaultArgsShape $ignoreDefaultArgs + */ + public function withIgnoreDefaultArgs(bool|array $ignoreDefaultArgs): self + { + $self = clone $this; + $self['ignoreDefaultArgs'] = $ignoreDefaultArgs; + + return $self; + } + + public function withIgnoreHTTPSErrors(bool $ignoreHTTPSErrors): self + { + $self = clone $this; + $self['ignoreHTTPSErrors'] = $ignoreHTTPSErrors; + + return $self; + } + + public function withLocale(string $locale): self + { + $self = clone $this; + $self['locale'] = $locale; + + return $self; + } + + public function withPreserveUserDataDir(bool $preserveUserDataDir): self + { + $self = clone $this; + $self['preserveUserDataDir'] = $preserveUserDataDir; + + return $self; + } + + /** + * @param ProxyShape $proxy + */ + public function withProxy(Proxy|array $proxy): self + { + $self = clone $this; + $self['proxy'] = $proxy; + + return $self; + } + + public function withUserDataDir(string $userDataDir): self + { + $self = clone $this; + $self['userDataDir'] = $userDataDir; + + return $self; + } + + /** + * @param ViewportShape $viewport + */ + public function withViewport(Viewport|array $viewport): self + { + $self = clone $this; + $self['viewport'] = $viewport; + + return $self; + } +} diff --git a/src/Sessions/SessionStartParams/Browser/LaunchOptions/IgnoreDefaultArgs.php b/src/Sessions/SessionStartParams/Browser/LaunchOptions/IgnoreDefaultArgs.php new file mode 100644 index 0000000..453660a --- /dev/null +++ b/src/Sessions/SessionStartParams/Browser/LaunchOptions/IgnoreDefaultArgs.php @@ -0,0 +1,26 @@ + + */ +final class IgnoreDefaultArgs implements ConverterSource +{ + use SdkUnion; + + /** + * @return list|array + */ + public static function variants(): array + { + return ['bool', new ListOf('string')]; + } +} diff --git a/src/Sessions/SessionStartParams/Browser/LaunchOptions/Proxy.php b/src/Sessions/SessionStartParams/Browser/LaunchOptions/Proxy.php new file mode 100644 index 0000000..ac3b76f --- /dev/null +++ b/src/Sessions/SessionStartParams/Browser/LaunchOptions/Proxy.php @@ -0,0 +1,109 @@ + */ + use SdkModel; + + #[Required] + public string $server; + + #[Optional] + public ?string $bypass; + + #[Optional] + public ?string $password; + + #[Optional] + public ?string $username; + + /** + * `new Proxy()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * Proxy::with(server: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new Proxy)->withServer(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with( + string $server, + ?string $bypass = null, + ?string $password = null, + ?string $username = null, + ): self { + $self = new self; + + $self['server'] = $server; + + null !== $bypass && $self['bypass'] = $bypass; + null !== $password && $self['password'] = $password; + null !== $username && $self['username'] = $username; + + return $self; + } + + public function withServer(string $server): self + { + $self = clone $this; + $self['server'] = $server; + + return $self; + } + + public function withBypass(string $bypass): self + { + $self = clone $this; + $self['bypass'] = $bypass; + + return $self; + } + + public function withPassword(string $password): self + { + $self = clone $this; + $self['password'] = $password; + + return $self; + } + + public function withUsername(string $username): self + { + $self = clone $this; + $self['username'] = $username; + + return $self; + } +} diff --git a/src/Sessions/SessionStartParams/Browser/LaunchOptions/Viewport.php b/src/Sessions/SessionStartParams/Browser/LaunchOptions/Viewport.php new file mode 100644 index 0000000..7536799 --- /dev/null +++ b/src/Sessions/SessionStartParams/Browser/LaunchOptions/Viewport.php @@ -0,0 +1,74 @@ + */ + use SdkModel; + + #[Required] + public float $height; + + #[Required] + public float $width; + + /** + * `new Viewport()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * Viewport::with(height: ..., width: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new Viewport)->withHeight(...)->withWidth(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with(float $height, float $width): self + { + $self = new self; + + $self['height'] = $height; + $self['width'] = $width; + + return $self; + } + + public function withHeight(float $height): self + { + $self = clone $this; + $self['height'] = $height; + + return $self; + } + + public function withWidth(float $width): self + { + $self = clone $this; + $self['width'] = $width; + + return $self; + } +} diff --git a/src/Sessions/SessionStartParams/Browser/Type.php b/src/Sessions/SessionStartParams/Browser/Type.php new file mode 100644 index 0000000..c6baf44 --- /dev/null +++ b/src/Sessions/SessionStartParams/Browser/Type.php @@ -0,0 +1,15 @@ +, + * timeout?: float|null, + * userMetadata?: array|null, + * } + */ +final class BrowserbaseSessionCreateParams implements BaseModel +{ + /** @use SdkModel */ + use SdkModel; + + #[Optional] + public ?BrowserSettings $browserSettings; + + #[Optional('extensionId')] + public ?string $extensionID; + + #[Optional] + public ?bool $keepAlive; + + #[Optional('projectId')] + public ?string $projectID; + + /** @var bool|list|null $proxies */ + #[Optional(union: Proxies::class)] + public bool|array|null $proxies; + + /** @var value-of|null $region */ + #[Optional(enum: Region::class)] + public ?string $region; + + #[Optional] + public ?float $timeout; + + /** @var array|null $userMetadata */ + #[Optional(map: 'mixed')] + public ?array $userMetadata; + + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param BrowserSettingsShape $browserSettings + * @param ProxiesShape $proxies + * @param Region|value-of $region + * @param array $userMetadata + */ + public static function with( + BrowserSettings|array|null $browserSettings = null, + ?string $extensionID = null, + ?bool $keepAlive = null, + ?string $projectID = null, + bool|array|null $proxies = null, + Region|string|null $region = null, + ?float $timeout = null, + ?array $userMetadata = null, + ): self { + $self = new self; + + null !== $browserSettings && $self['browserSettings'] = $browserSettings; + null !== $extensionID && $self['extensionID'] = $extensionID; + null !== $keepAlive && $self['keepAlive'] = $keepAlive; + null !== $projectID && $self['projectID'] = $projectID; + null !== $proxies && $self['proxies'] = $proxies; + null !== $region && $self['region'] = $region; + null !== $timeout && $self['timeout'] = $timeout; + null !== $userMetadata && $self['userMetadata'] = $userMetadata; + + return $self; + } + + /** + * @param BrowserSettingsShape $browserSettings + */ + public function withBrowserSettings( + BrowserSettings|array $browserSettings + ): self { + $self = clone $this; + $self['browserSettings'] = $browserSettings; + + return $self; + } + + public function withExtensionID(string $extensionID): self + { + $self = clone $this; + $self['extensionID'] = $extensionID; + + return $self; + } + + public function withKeepAlive(bool $keepAlive): self + { + $self = clone $this; + $self['keepAlive'] = $keepAlive; + + return $self; + } + + public function withProjectID(string $projectID): self + { + $self = clone $this; + $self['projectID'] = $projectID; + + return $self; + } + + /** + * @param ProxiesShape $proxies + */ + public function withProxies(bool|array $proxies): self + { + $self = clone $this; + $self['proxies'] = $proxies; + + return $self; + } + + /** + * @param Region|value-of $region + */ + public function withRegion(Region|string $region): self + { + $self = clone $this; + $self['region'] = $region; + + return $self; + } + + public function withTimeout(float $timeout): self + { + $self = clone $this; + $self['timeout'] = $timeout; + + return $self; + } + + /** + * @param array $userMetadata + */ + public function withUserMetadata(array $userMetadata): self + { + $self = clone $this; + $self['userMetadata'] = $userMetadata; + + return $self; + } +} diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings.php new file mode 100644 index 0000000..4c21ce5 --- /dev/null +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings.php @@ -0,0 +1,183 @@ + */ + use SdkModel; + + #[Optional] + public ?bool $advancedStealth; + + #[Optional] + public ?bool $blockAds; + + #[Optional] + public ?Context $context; + + #[Optional('extensionId')] + public ?string $extensionID; + + #[Optional] + public ?Fingerprint $fingerprint; + + #[Optional] + public ?bool $logSession; + + #[Optional] + public ?bool $recordSession; + + #[Optional] + public ?bool $solveCaptchas; + + #[Optional] + public ?Viewport $viewport; + + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param ContextShape $context + * @param FingerprintShape $fingerprint + * @param ViewportShape $viewport + */ + public static function with( + ?bool $advancedStealth = null, + ?bool $blockAds = null, + Context|array|null $context = null, + ?string $extensionID = null, + Fingerprint|array|null $fingerprint = null, + ?bool $logSession = null, + ?bool $recordSession = null, + ?bool $solveCaptchas = null, + Viewport|array|null $viewport = null, + ): self { + $self = new self; + + null !== $advancedStealth && $self['advancedStealth'] = $advancedStealth; + null !== $blockAds && $self['blockAds'] = $blockAds; + null !== $context && $self['context'] = $context; + null !== $extensionID && $self['extensionID'] = $extensionID; + null !== $fingerprint && $self['fingerprint'] = $fingerprint; + null !== $logSession && $self['logSession'] = $logSession; + null !== $recordSession && $self['recordSession'] = $recordSession; + null !== $solveCaptchas && $self['solveCaptchas'] = $solveCaptchas; + null !== $viewport && $self['viewport'] = $viewport; + + return $self; + } + + public function withAdvancedStealth(bool $advancedStealth): self + { + $self = clone $this; + $self['advancedStealth'] = $advancedStealth; + + return $self; + } + + public function withBlockAds(bool $blockAds): self + { + $self = clone $this; + $self['blockAds'] = $blockAds; + + return $self; + } + + /** + * @param ContextShape $context + */ + public function withContext(Context|array $context): self + { + $self = clone $this; + $self['context'] = $context; + + return $self; + } + + public function withExtensionID(string $extensionID): self + { + $self = clone $this; + $self['extensionID'] = $extensionID; + + return $self; + } + + /** + * @param FingerprintShape $fingerprint + */ + public function withFingerprint(Fingerprint|array $fingerprint): self + { + $self = clone $this; + $self['fingerprint'] = $fingerprint; + + return $self; + } + + public function withLogSession(bool $logSession): self + { + $self = clone $this; + $self['logSession'] = $logSession; + + return $self; + } + + public function withRecordSession(bool $recordSession): self + { + $self = clone $this; + $self['recordSession'] = $recordSession; + + return $self; + } + + public function withSolveCaptchas(bool $solveCaptchas): self + { + $self = clone $this; + $self['solveCaptchas'] = $solveCaptchas; + + return $self; + } + + /** + * @param ViewportShape $viewport + */ + public function withViewport(Viewport|array $viewport): self + { + $self = clone $this; + $self['viewport'] = $viewport; + + return $self; + } +} diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Context.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Context.php new file mode 100644 index 0000000..b270035 --- /dev/null +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Context.php @@ -0,0 +1,76 @@ + */ + use SdkModel; + + #[Required] + public string $id; + + #[Optional] + public ?bool $persist; + + /** + * `new Context()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * Context::with(id: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new Context)->withID(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with(string $id, ?bool $persist = null): self + { + $self = new self; + + $self['id'] = $id; + + null !== $persist && $self['persist'] = $persist; + + return $self; + } + + public function withID(string $id): self + { + $self = clone $this; + $self['id'] = $id; + + return $self; + } + + public function withPersist(bool $persist): self + { + $self = clone $this; + $self['persist'] = $persist; + + return $self; + } +} diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Fingerprint.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Fingerprint.php new file mode 100644 index 0000000..831a5e8 --- /dev/null +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Fingerprint.php @@ -0,0 +1,158 @@ +>|null, + * devices?: list>|null, + * httpVersion?: null|HTTPVersion|value-of, + * locales?: list|null, + * operatingSystems?: list>|null, + * screen?: null|Screen|ScreenShape, + * } + */ +final class Fingerprint implements BaseModel +{ + /** @use SdkModel */ + use SdkModel; + + /** @var list>|null $browsers */ + #[Optional(list: Browser::class)] + public ?array $browsers; + + /** @var list>|null $devices */ + #[Optional(list: Device::class)] + public ?array $devices; + + /** @var value-of|null $httpVersion */ + #[Optional(enum: HTTPVersion::class)] + public ?string $httpVersion; + + /** @var list|null $locales */ + #[Optional(list: 'string')] + public ?array $locales; + + /** @var list>|null $operatingSystems */ + #[Optional(list: OperatingSystem::class)] + public ?array $operatingSystems; + + #[Optional] + public ?Screen $screen; + + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param list> $browsers + * @param list> $devices + * @param HTTPVersion|value-of $httpVersion + * @param list $locales + * @param list> $operatingSystems + * @param ScreenShape $screen + */ + public static function with( + ?array $browsers = null, + ?array $devices = null, + HTTPVersion|string|null $httpVersion = null, + ?array $locales = null, + ?array $operatingSystems = null, + Screen|array|null $screen = null, + ): self { + $self = new self; + + null !== $browsers && $self['browsers'] = $browsers; + null !== $devices && $self['devices'] = $devices; + null !== $httpVersion && $self['httpVersion'] = $httpVersion; + null !== $locales && $self['locales'] = $locales; + null !== $operatingSystems && $self['operatingSystems'] = $operatingSystems; + null !== $screen && $self['screen'] = $screen; + + return $self; + } + + /** + * @param list> $browsers + */ + public function withBrowsers(array $browsers): self + { + $self = clone $this; + $self['browsers'] = $browsers; + + return $self; + } + + /** + * @param list> $devices + */ + public function withDevices(array $devices): self + { + $self = clone $this; + $self['devices'] = $devices; + + return $self; + } + + /** + * @param HTTPVersion|value-of $httpVersion + */ + public function withHTTPVersion(HTTPVersion|string $httpVersion): self + { + $self = clone $this; + $self['httpVersion'] = $httpVersion; + + return $self; + } + + /** + * @param list $locales + */ + public function withLocales(array $locales): self + { + $self = clone $this; + $self['locales'] = $locales; + + return $self; + } + + /** + * @param list> $operatingSystems + */ + public function withOperatingSystems(array $operatingSystems): self + { + $self = clone $this; + $self['operatingSystems'] = $operatingSystems; + + return $self; + } + + /** + * @param ScreenShape $screen + */ + public function withScreen(Screen|array $screen): self + { + $self = clone $this; + $self['screen'] = $screen; + + return $self; + } +} diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Fingerprint/Browser.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Fingerprint/Browser.php new file mode 100644 index 0000000..54a65f2 --- /dev/null +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Fingerprint/Browser.php @@ -0,0 +1,16 @@ + */ + use SdkModel; + + #[Optional] + public ?float $maxHeight; + + #[Optional] + public ?float $maxWidth; + + #[Optional] + public ?float $minHeight; + + #[Optional] + public ?float $minWidth; + + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with( + ?float $maxHeight = null, + ?float $maxWidth = null, + ?float $minHeight = null, + ?float $minWidth = null, + ): self { + $self = new self; + + null !== $maxHeight && $self['maxHeight'] = $maxHeight; + null !== $maxWidth && $self['maxWidth'] = $maxWidth; + null !== $minHeight && $self['minHeight'] = $minHeight; + null !== $minWidth && $self['minWidth'] = $minWidth; + + return $self; + } + + public function withMaxHeight(float $maxHeight): self + { + $self = clone $this; + $self['maxHeight'] = $maxHeight; + + return $self; + } + + public function withMaxWidth(float $maxWidth): self + { + $self = clone $this; + $self['maxWidth'] = $maxWidth; + + return $self; + } + + public function withMinHeight(float $minHeight): self + { + $self = clone $this; + $self['minHeight'] = $minHeight; + + return $self; + } + + public function withMinWidth(float $minWidth): self + { + $self = clone $this; + $self['minWidth'] = $minWidth; + + return $self; + } +} diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Viewport.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Viewport.php new file mode 100644 index 0000000..020cca8 --- /dev/null +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Viewport.php @@ -0,0 +1,60 @@ + */ + use SdkModel; + + #[Optional] + public ?float $height; + + #[Optional] + public ?float $width; + + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with(?float $height = null, ?float $width = null): self + { + $self = new self; + + null !== $height && $self['height'] = $height; + null !== $width && $self['width'] = $width; + + return $self; + } + + public function withHeight(float $height): self + { + $self = clone $this; + $self['height'] = $height; + + return $self; + } + + public function withWidth(float $width): self + { + $self = clone $this; + $self['width'] = $width; + + return $self; + } +} diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies.php new file mode 100644 index 0000000..460a137 --- /dev/null +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies.php @@ -0,0 +1,29 @@ + + */ +final class Proxies implements ConverterSource +{ + use SdkUnion; + + /** + * @return list|array + */ + public static function variants(): array + { + return ['bool', new ListOf(UnionMember1::class)]; + } +} diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1.php new file mode 100644 index 0000000..dcb373d --- /dev/null +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1.php @@ -0,0 +1,30 @@ +|array + */ + public static function variants(): array + { + return [BrowserbaseProxyConfig::class, ExternalProxyConfig::class]; + } +} diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig.php new file mode 100644 index 0000000..4d4b609 --- /dev/null +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig.php @@ -0,0 +1,109 @@ +, + * domainPattern?: string|null, + * geolocation?: null|Geolocation|GeolocationShape, + * } + */ +final class BrowserbaseProxyConfig implements BaseModel +{ + /** @use SdkModel */ + use SdkModel; + + /** @var value-of $type */ + #[Required(enum: Type::class)] + public string $type; + + #[Optional] + public ?string $domainPattern; + + #[Optional] + public ?Geolocation $geolocation; + + /** + * `new BrowserbaseProxyConfig()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * BrowserbaseProxyConfig::with(type: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new BrowserbaseProxyConfig)->withType(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param Type|value-of $type + * @param GeolocationShape $geolocation + */ + public static function with( + Type|string $type, + ?string $domainPattern = null, + Geolocation|array|null $geolocation = null, + ): self { + $self = new self; + + $self['type'] = $type; + + null !== $domainPattern && $self['domainPattern'] = $domainPattern; + null !== $geolocation && $self['geolocation'] = $geolocation; + + return $self; + } + + /** + * @param Type|value-of $type + */ + public function withType(Type|string $type): self + { + $self = clone $this; + $self['type'] = $type; + + return $self; + } + + public function withDomainPattern(string $domainPattern): self + { + $self = clone $this; + $self['domainPattern'] = $domainPattern; + + return $self; + } + + /** + * @param GeolocationShape $geolocation + */ + public function withGeolocation(Geolocation|array $geolocation): self + { + $self = clone $this; + $self['geolocation'] = $geolocation; + + return $self; + } +} diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig/Geolocation.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig/Geolocation.php new file mode 100644 index 0000000..93deda1 --- /dev/null +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig/Geolocation.php @@ -0,0 +1,93 @@ + */ + use SdkModel; + + #[Required] + public string $country; + + #[Optional] + public ?string $city; + + #[Optional] + public ?string $state; + + /** + * `new Geolocation()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * Geolocation::with(country: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new Geolocation)->withCountry(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with( + string $country, + ?string $city = null, + ?string $state = null + ): self { + $self = new self; + + $self['country'] = $country; + + null !== $city && $self['city'] = $city; + null !== $state && $self['state'] = $state; + + return $self; + } + + public function withCountry(string $country): self + { + $self = clone $this; + $self['country'] = $country; + + return $self; + } + + public function withCity(string $city): self + { + $self = clone $this; + $self['city'] = $city; + + return $self; + } + + public function withState(string $state): self + { + $self = clone $this; + $self['state'] = $state; + + return $self; + } +} diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig/Type.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig/Type.php new file mode 100644 index 0000000..32496f9 --- /dev/null +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig/Type.php @@ -0,0 +1,10 @@ +, + * domainPattern?: string|null, + * password?: string|null, + * username?: string|null, + * } + */ +final class ExternalProxyConfig implements BaseModel +{ + /** @use SdkModel */ + use SdkModel; + + #[Required] + public string $server; + + /** @var value-of $type */ + #[Required(enum: Type::class)] + public string $type; + + #[Optional] + public ?string $domainPattern; + + #[Optional] + public ?string $password; + + #[Optional] + public ?string $username; + + /** + * `new ExternalProxyConfig()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * ExternalProxyConfig::with(server: ..., type: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new ExternalProxyConfig)->withServer(...)->withType(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param Type|value-of $type + */ + public static function with( + string $server, + Type|string $type, + ?string $domainPattern = null, + ?string $password = null, + ?string $username = null, + ): self { + $self = new self; + + $self['server'] = $server; + $self['type'] = $type; + + null !== $domainPattern && $self['domainPattern'] = $domainPattern; + null !== $password && $self['password'] = $password; + null !== $username && $self['username'] = $username; + + return $self; + } + + public function withServer(string $server): self + { + $self = clone $this; + $self['server'] = $server; + + return $self; + } + + /** + * @param Type|value-of $type + */ + public function withType(Type|string $type): self + { + $self = clone $this; + $self['type'] = $type; + + return $self; + } + + public function withDomainPattern(string $domainPattern): self + { + $self = clone $this; + $self['domainPattern'] = $domainPattern; + + return $self; + } + + public function withPassword(string $password): self + { + $self = clone $this; + $self['password'] = $password; + + return $self; + } + + public function withUsername(string $username): self + { + $self = clone $this; + $self['username'] = $username; + + return $self; + } +} diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/ExternalProxyConfig/Type.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/ExternalProxyConfig/Type.php new file mode 100644 index 0000000..dd4a6c6 --- /dev/null +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/ExternalProxyConfig/Type.php @@ -0,0 +1,10 @@ + */ + use SdkModel; + + #[Required] + public Data $data; + + #[Required] + public bool $success; + + /** + * `new SessionStartResponse()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * SessionStartResponse::with(data: ..., success: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new SessionStartResponse)->withData(...)->withSuccess(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param DataShape $data + */ + public static function with(Data|array $data, bool $success): self + { + $self = new self; + + $self['data'] = $data; + $self['success'] = $success; + + return $self; + } + + /** + * @param DataShape $data + */ + public function withData(Data|array $data): self + { + $self = clone $this; + $self['data'] = $data; + + return $self; + } + + public function withSuccess(bool $success): self + { + $self = clone $this; + $self['success'] = $success; + + return $self; + } +} diff --git a/src/Sessions/SessionStartResponse/Data.php b/src/Sessions/SessionStartResponse/Data.php new file mode 100644 index 0000000..461235a --- /dev/null +++ b/src/Sessions/SessionStartResponse/Data.php @@ -0,0 +1,80 @@ + */ + use SdkModel; + + #[Required] + public bool $available; + + /** + * Unique session identifier. + */ + #[Required('sessionId')] + public string $sessionID; + + /** + * `new Data()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * Data::with(available: ..., sessionID: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new Data)->withAvailable(...)->withSessionID(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with(bool $available, string $sessionID): self + { + $self = new self; + + $self['available'] = $available; + $self['sessionID'] = $sessionID; + + return $self; + } + + public function withAvailable(bool $available): self + { + $self = clone $this; + $self['available'] = $available; + + return $self; + } + + /** + * Unique session identifier. + */ + public function withSessionID(string $sessionID): self + { + $self = clone $this; + $self['sessionID'] = $sessionID; + + return $self; + } +} diff --git a/tests/Services/SessionsTest.php b/tests/Services/SessionsTest.php index 4fb48eb..7700243 100644 --- a/tests/Services/SessionsTest.php +++ b/tests/Services/SessionsTest.php @@ -6,6 +6,13 @@ use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Stagehand\Client; +use Stagehand\Sessions\SessionActResponse; +use Stagehand\Sessions\SessionEndResponse; +use Stagehand\Sessions\SessionExecuteResponse; +use Stagehand\Sessions\SessionExtractResponse; +use Stagehand\Sessions\SessionNavigateResponse; +use Stagehand\Sessions\SessionObserveResponse; +use Stagehand\Sessions\SessionStartResponse; use Tests\UnsupportedMockTests; /** @@ -38,10 +45,39 @@ public function testAct(): void $this->markTestSkipped('Prism tests are disabled'); } - $result = $this->client->sessions->act((object) []); + $result = $this->client->sessions->act( + 'c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123', + input: 'Click the login button' + ); // @phpstan-ignore-next-line method.alreadyNarrowedType - $this->assertIsNotResource($result); + $this->assertInstanceOf(SessionActResponse::class, $result); + } + + #[Test] + public function testActWithOptionalParams(): void + { + if (UnsupportedMockTests::$skip) { + $this->markTestSkipped('Prism tests are disabled'); + } + + $result = $this->client->sessions->act( + 'c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123', + input: 'Click the login button', + frameID: 'frameId', + options: [ + 'model' => 'string', + 'timeout' => 30000, + 'variables' => ['username' => 'john_doe'], + ], + xLanguage: 'typescript', + xSDKVersion: '3.0.6', + xSentAt: new \DateTimeImmutable('2025-01-15T10:30:00.000Z'), + xStreamResponse: 'true', + ); + + // @phpstan-ignore-next-line method.alreadyNarrowedType + $this->assertInstanceOf(SessionActResponse::class, $result); } #[Test] @@ -51,23 +87,59 @@ public function testEnd(): void $this->markTestSkipped('Prism tests are disabled'); } - $result = $this->client->sessions->end((object) []); + $result = $this->client->sessions->end( + 'c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123' + ); // @phpstan-ignore-next-line method.alreadyNarrowedType - $this->assertIsNotResource($result); + $this->assertInstanceOf(SessionEndResponse::class, $result); } #[Test] - public function testExecuteAgent(): void + public function testExecute(): void { if (UnsupportedMockTests::$skip) { $this->markTestSkipped('Prism tests are disabled'); } - $result = $this->client->sessions->executeAgent((object) []); + $result = $this->client->sessions->execute( + 'c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123', + agentConfig: [], + executeOptions: [ + 'instruction' => 'Log in with username \'demo\' and password \'test123\', then navigate to settings', + ], + ); + + // @phpstan-ignore-next-line method.alreadyNarrowedType + $this->assertInstanceOf(SessionExecuteResponse::class, $result); + } + + #[Test] + public function testExecuteWithOptionalParams(): void + { + if (UnsupportedMockTests::$skip) { + $this->markTestSkipped('Prism tests are disabled'); + } + + $result = $this->client->sessions->execute( + 'c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123', + agentConfig: [ + 'cua' => true, 'model' => 'string', 'systemPrompt' => 'systemPrompt', + ], + executeOptions: [ + 'instruction' => 'Log in with username \'demo\' and password \'test123\', then navigate to settings', + 'highlightCursor' => true, + 'maxSteps' => 20, + ], + frameID: 'frameId', + xLanguage: 'typescript', + xSDKVersion: '3.0.6', + xSentAt: new \DateTimeImmutable('2025-01-15T10:30:00.000Z'), + xStreamResponse: 'true', + ); // @phpstan-ignore-next-line method.alreadyNarrowedType - $this->assertIsNotResource($result); + $this->assertInstanceOf(SessionExecuteResponse::class, $result); } #[Test] @@ -77,10 +149,12 @@ public function testExtract(): void $this->markTestSkipped('Prism tests are disabled'); } - $result = $this->client->sessions->extract((object) []); + $result = $this->client->sessions->extract( + 'c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123' + ); // @phpstan-ignore-next-line method.alreadyNarrowedType - $this->assertIsNotResource($result); + $this->assertInstanceOf(SessionExtractResponse::class, $result); } #[Test] @@ -90,10 +164,37 @@ public function testNavigate(): void $this->markTestSkipped('Prism tests are disabled'); } - $result = $this->client->sessions->navigate((object) []); + $result = $this->client->sessions->navigate( + 'c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123', + url: 'https://example.com' + ); + + // @phpstan-ignore-next-line method.alreadyNarrowedType + $this->assertInstanceOf(SessionNavigateResponse::class, $result); + } + + #[Test] + public function testNavigateWithOptionalParams(): void + { + if (UnsupportedMockTests::$skip) { + $this->markTestSkipped('Prism tests are disabled'); + } + + $result = $this->client->sessions->navigate( + 'c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123', + url: 'https://example.com', + frameID: 'frameId', + options: [ + 'referer' => 'referer', 'timeout' => 30000, 'waitUntil' => 'networkidle', + ], + xLanguage: 'typescript', + xSDKVersion: '3.0.6', + xSentAt: new \DateTimeImmutable('2025-01-15T10:30:00.000Z'), + xStreamResponse: 'true', + ); // @phpstan-ignore-next-line method.alreadyNarrowedType - $this->assertIsNotResource($result); + $this->assertInstanceOf(SessionNavigateResponse::class, $result); } #[Test] @@ -103,10 +204,12 @@ public function testObserve(): void $this->markTestSkipped('Prism tests are disabled'); } - $result = $this->client->sessions->observe((object) []); + $result = $this->client->sessions->observe( + 'c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123' + ); // @phpstan-ignore-next-line method.alreadyNarrowedType - $this->assertIsNotResource($result); + $this->assertInstanceOf(SessionObserveResponse::class, $result); } #[Test] @@ -116,9 +219,98 @@ public function testStart(): void $this->markTestSkipped('Prism tests are disabled'); } - $result = $this->client->sessions->start(); + $result = $this->client->sessions->start(modelName: 'gpt-4o'); + + // @phpstan-ignore-next-line method.alreadyNarrowedType + $this->assertInstanceOf(SessionStartResponse::class, $result); + } + + #[Test] + public function testStartWithOptionalParams(): void + { + if (UnsupportedMockTests::$skip) { + $this->markTestSkipped('Prism tests are disabled'); + } + + $result = $this->client->sessions->start( + modelName: 'gpt-4o', + actTimeoutMs: 30000, + browser: [ + 'cdpURL' => 'ws://localhost:9222', + 'launchOptions' => [ + 'acceptDownloads' => true, + 'args' => ['string'], + 'cdpURL' => 'cdpUrl', + 'chromiumSandbox' => true, + 'connectTimeoutMs' => 0, + 'deviceScaleFactor' => 0, + 'devtools' => true, + 'downloadsPath' => 'downloadsPath', + 'executablePath' => 'executablePath', + 'hasTouch' => true, + 'headless' => true, + 'ignoreDefaultArgs' => true, + 'ignoreHTTPSErrors' => true, + 'locale' => 'locale', + 'preserveUserDataDir' => true, + 'proxy' => [ + 'server' => 'server', + 'bypass' => 'bypass', + 'password' => 'password', + 'username' => 'username', + ], + 'userDataDir' => 'userDataDir', + 'viewport' => ['height' => 0, 'width' => 0], + ], + 'type' => 'local', + ], + browserbaseSessionCreateParams: [ + 'browserSettings' => [ + 'advancedStealth' => true, + 'blockAds' => true, + 'context' => ['id' => 'id', 'persist' => true], + 'extensionID' => 'extensionId', + 'fingerprint' => [ + 'browsers' => ['chrome'], + 'devices' => ['desktop'], + 'httpVersion' => '1', + 'locales' => ['string'], + 'operatingSystems' => ['android'], + 'screen' => [ + 'maxHeight' => 0, + 'maxWidth' => 0, + 'minHeight' => 0, + 'minWidth' => 0, + ], + ], + 'logSession' => true, + 'recordSession' => true, + 'solveCaptchas' => true, + 'viewport' => ['height' => 0, 'width' => 0], + ], + 'extensionID' => 'extensionId', + 'keepAlive' => true, + 'projectID' => 'projectId', + 'proxies' => true, + 'region' => 'us-west-2', + 'timeout' => 0, + 'userMetadata' => ['foo' => 'bar'], + ], + browserbaseSessionID: 'browserbaseSessionID', + debugDom: true, + domSettleTimeoutMs: 5000, + experimental: true, + selfHeal: true, + systemPrompt: 'systemPrompt', + verbose: 1, + waitForCaptchaSolves: true, + xLanguage: 'typescript', + xSDKVersion: '3.0.6', + xSentAt: new \DateTimeImmutable('2025-01-15T10:30:00.000Z'), + xStreamResponse: 'true', + ); // @phpstan-ignore-next-line method.alreadyNarrowedType - $this->assertIsNotResource($result); + $this->assertInstanceOf(SessionStartResponse::class, $result); } } From 2748aea3da35936913f4643a70fb2aff6f61a562 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 18:23:01 +0000 Subject: [PATCH 07/29] feat(api): manual updates --- .stats.yml | 6 +++--- README.md | 16 +++++++++------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/.stats.yml b/.stats.yml index 87bd24b..a5338dd 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-349e1b0f6291eedd731c1660155a50adcb3424fb8cd9e17bbdc0939ff3bbffcd.yml -openapi_spec_hash: 456b593ea71d72bc31a6338a25363e9f -config_hash: 5f6b5ec6e84fb01932ba87c6a9623d9b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-e6a9dca1a93568e403ac72128d86f30c8c3f1336d4b67017d7e61b1836f10f47.yml +openapi_spec_hash: ef01e0649bb0e283df0aa81c369649df +config_hash: abc9d1eb9779bb5629eaed7074c42809 diff --git a/README.md b/README.md index 165ffd6..05bafd9 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,10 @@ $client = new Client( modelAPIKey: getenv('MODEL_API_KEY') ?: 'My Model API Key', ); -$response = $client->sessions->act('c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123'); +$response = $client->sessions->act( + 'c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123', + input: 'click the first link on the page', +); var_dump($response->data); ``` @@ -77,7 +80,7 @@ When the library is unable to connect to the API, or if the API returns a non-su use Stagehand\Core\Exceptions\APIConnectionException; try { - $response = $client->sessions->act('c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123'); + $response = $client->sessions->start(modelName: 'gpt-4o'); } catch (APIConnectionException $e) { echo "The server could not be reached", PHP_EOL; var_dump($e->getPrevious()); @@ -123,9 +126,8 @@ use Stagehand\RequestOptions; $client = new Client(maxRetries: 0); // Or, configure per-request: -$result = $client->sessions->act( - 'c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123', - requestOptions: RequestOptions::with(maxRetries: 5), +$result = $client->sessions->start( + modelName: 'gpt-4o', requestOptions: RequestOptions::with(maxRetries: 5) ); ``` @@ -144,8 +146,8 @@ Note: the `extra*` parameters of the same name overrides the documented paramete use Stagehand\RequestOptions; -$response = $client->sessions->act( - 'c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123', +$response = $client->sessions->start( + modelName: 'gpt-4o', requestOptions: RequestOptions::with( extraQueryParams: ['my_query_parameter' => 'value'], extraBodyParams: ['my_body_parameter' => 'value'], From 050193250e7e1092ba83b97d4735e80328492188 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 18:25:02 +0000 Subject: [PATCH 08/29] feat(api): manual updates --- .stats.yml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index a5338dd..4bcf91f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-e6a9dca1a93568e403ac72128d86f30c8c3f1336d4b67017d7e61b1836f10f47.yml openapi_spec_hash: ef01e0649bb0e283df0aa81c369649df -config_hash: abc9d1eb9779bb5629eaed7074c42809 +config_hash: 0f2a6f228fb92683466c107fce3bcd21 diff --git a/README.md b/README.md index 05bafd9..db1e955 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ $client = new Client( ); $response = $client->sessions->act( - 'c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123', + '00000000-your-session-id-000000000000', input: 'click the first link on the page', ); From 3aac7a31a6a32ef739f918fba6effb6081b7c10a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 18:27:18 +0000 Subject: [PATCH 09/29] feat(api): manual updates --- .stats.yml | 2 +- README.md | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4bcf91f..2790605 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-e6a9dca1a93568e403ac72128d86f30c8c3f1336d4b67017d7e61b1836f10f47.yml openapi_spec_hash: ef01e0649bb0e283df0aa81c369649df -config_hash: 0f2a6f228fb92683466c107fce3bcd21 +config_hash: 88e87ba7021be93d267ecfc8f5e6b891 diff --git a/README.md b/README.md index db1e955..397b274 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ When the library is unable to connect to the API, or if the API returns a non-su use Stagehand\Core\Exceptions\APIConnectionException; try { - $response = $client->sessions->start(modelName: 'gpt-4o'); + $response = $client->sessions->start(modelName: 'openai/gpt-5-nano'); } catch (APIConnectionException $e) { echo "The server could not be reached", PHP_EOL; var_dump($e->getPrevious()); @@ -127,7 +127,8 @@ $client = new Client(maxRetries: 0); // Or, configure per-request: $result = $client->sessions->start( - modelName: 'gpt-4o', requestOptions: RequestOptions::with(maxRetries: 5) + modelName: 'openai/gpt-5-nano', + requestOptions: RequestOptions::with(maxRetries: 5), ); ``` @@ -147,7 +148,7 @@ Note: the `extra*` parameters of the same name overrides the documented paramete use Stagehand\RequestOptions; $response = $client->sessions->start( - modelName: 'gpt-4o', + modelName: 'openai/gpt-5-nano', requestOptions: RequestOptions::with( extraQueryParams: ['my_query_parameter' => 'value'], extraBodyParams: ['my_body_parameter' => 'value'], From 7d515687b0aca206c9124b270a4f1f0ab84fe467 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 18:47:00 +0000 Subject: [PATCH 10/29] feat(api): manual updates --- .stats.yml | 4 +- src/ServiceContracts/SessionsContract.php | 4 +- src/Services/SessionsRawService.php | 2 +- src/Services/SessionsService.php | 4 +- src/Sessions/SessionActResponse.php | 6 +++ src/Sessions/SessionEndResponse.php | 32 ++------------- src/Sessions/SessionExecuteResponse.php | 6 +++ src/Sessions/SessionExtractResponse.php | 6 +++ src/Sessions/SessionNavigateResponse.php | 6 +++ src/Sessions/SessionObserveResponse.php | 6 +++ src/Sessions/SessionStartParams.php | 8 ++-- .../UnionMember1/BrowserbaseProxyConfig.php | 40 +++---------------- .../BrowserbaseProxyConfig/Type.php | 10 ----- .../UnionMember1/ExternalProxyConfig.php | 30 ++++---------- .../UnionMember1/ExternalProxyConfig/Type.php | 10 ----- src/Sessions/SessionStartResponse.php | 6 +++ 16 files changed, 62 insertions(+), 118 deletions(-) delete mode 100644 src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig/Type.php delete mode 100644 src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/ExternalProxyConfig/Type.php diff --git a/.stats.yml b/.stats.yml index 2790605..08f0cef 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-e6a9dca1a93568e403ac72128d86f30c8c3f1336d4b67017d7e61b1836f10f47.yml -openapi_spec_hash: ef01e0649bb0e283df0aa81c369649df +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-d571232203ef4e00986a3245224267db6f8aaffdad57780f712e0694dc8d9e37.yml +openapi_spec_hash: d5d635dd7b24a2e1255c6f2a895253ff config_hash: 88e87ba7021be93d267ecfc8f5e6b891 diff --git a/src/ServiceContracts/SessionsContract.php b/src/ServiceContracts/SessionsContract.php index 39a68ff..a2ed8b5 100644 --- a/src/ServiceContracts/SessionsContract.php +++ b/src/ServiceContracts/SessionsContract.php @@ -270,7 +270,7 @@ public function observe( * @param bool $experimental Body param: * @param bool $selfHeal Body param: Enable self-healing for failed actions * @param string $systemPrompt Body param: Custom system prompt for AI operations - * @param float $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) + * @param int $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) * @param bool $waitForCaptchaSolves Body param: * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionStartParams\XLanguage $xLanguage Header param: Client SDK language * @param string $xSDKVersion Header param: Version of the Stagehand SDK @@ -290,7 +290,7 @@ public function start( ?bool $experimental = null, ?bool $selfHeal = null, ?string $systemPrompt = null, - ?float $verbose = null, + ?int $verbose = null, ?bool $waitForCaptchaSolves = null, string|\Stagehand\Sessions\SessionStartParams\XLanguage|null $xLanguage = null, ?string $xSDKVersion = null, diff --git a/src/Services/SessionsRawService.php b/src/Services/SessionsRawService.php index 0b6330c..484541d 100644 --- a/src/Services/SessionsRawService.php +++ b/src/Services/SessionsRawService.php @@ -444,7 +444,7 @@ public function observe( * experimental?: bool, * selfHeal?: bool, * systemPrompt?: string, - * verbose?: float, + * verbose?: int, * waitForCaptchaSolves?: bool, * xLanguage?: 'typescript'|'python'|'playground'|SessionStartParams\XLanguage, * xSDKVersion?: string, diff --git a/src/Services/SessionsService.php b/src/Services/SessionsService.php index e35637e..05a4fcc 100644 --- a/src/Services/SessionsService.php +++ b/src/Services/SessionsService.php @@ -400,7 +400,7 @@ public function observe( * @param bool $experimental Body param: * @param bool $selfHeal Body param: Enable self-healing for failed actions * @param string $systemPrompt Body param: Custom system prompt for AI operations - * @param float $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) + * @param int $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) * @param bool $waitForCaptchaSolves Body param: * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionStartParams\XLanguage $xLanguage Header param: Client SDK language * @param string $xSDKVersion Header param: Version of the Stagehand SDK @@ -420,7 +420,7 @@ public function start( ?bool $experimental = null, ?bool $selfHeal = null, ?string $systemPrompt = null, - ?float $verbose = null, + ?int $verbose = null, ?bool $waitForCaptchaSolves = null, string|\Stagehand\Sessions\SessionStartParams\XLanguage|null $xLanguage = null, ?string $xSDKVersion = null, diff --git a/src/Sessions/SessionActResponse.php b/src/Sessions/SessionActResponse.php index ff7f89d..086b152 100644 --- a/src/Sessions/SessionActResponse.php +++ b/src/Sessions/SessionActResponse.php @@ -24,6 +24,9 @@ final class SessionActResponse implements BaseModel #[Required] public Data $data; + /** + * Indicates whether the request was successful. + */ #[Required] public bool $success; @@ -74,6 +77,9 @@ public function withData(Data|array $data): self return $self; } + /** + * Indicates whether the request was successful. + */ public function withSuccess(bool $success): self { $self = clone $this; diff --git a/src/Sessions/SessionEndResponse.php b/src/Sessions/SessionEndResponse.php index 1fabdd3..8253d13 100644 --- a/src/Sessions/SessionEndResponse.php +++ b/src/Sessions/SessionEndResponse.php @@ -17,22 +17,8 @@ final class SessionEndResponse implements BaseModel use SdkModel; #[Required] - public bool $success; + public bool $success = true; - /** - * `new SessionEndResponse()` is missing required properties by the API. - * - * To enforce required parameters use - * ``` - * SessionEndResponse::with(success: ...) - * ``` - * - * Otherwise ensure the following setters are called - * - * ``` - * (new SessionEndResponse)->withSuccess(...) - * ``` - */ public function __construct() { $this->initialize(); @@ -43,20 +29,8 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. */ - public static function with(bool $success): self + public static function with(): self { - $self = new self; - - $self['success'] = $success; - - return $self; - } - - public function withSuccess(bool $success): self - { - $self = clone $this; - $self['success'] = $success; - - return $self; + return new self; } } diff --git a/src/Sessions/SessionExecuteResponse.php b/src/Sessions/SessionExecuteResponse.php index 2390f38..99e7670 100644 --- a/src/Sessions/SessionExecuteResponse.php +++ b/src/Sessions/SessionExecuteResponse.php @@ -24,6 +24,9 @@ final class SessionExecuteResponse implements BaseModel #[Required] public Data $data; + /** + * Indicates whether the request was successful. + */ #[Required] public bool $success; @@ -74,6 +77,9 @@ public function withData(Data|array $data): self return $self; } + /** + * Indicates whether the request was successful. + */ public function withSuccess(bool $success): self { $self = clone $this; diff --git a/src/Sessions/SessionExtractResponse.php b/src/Sessions/SessionExtractResponse.php index fe8cb66..e30a9bf 100644 --- a/src/Sessions/SessionExtractResponse.php +++ b/src/Sessions/SessionExtractResponse.php @@ -24,6 +24,9 @@ final class SessionExtractResponse implements BaseModel #[Required] public Data $data; + /** + * Indicates whether the request was successful. + */ #[Required] public bool $success; @@ -74,6 +77,9 @@ public function withData(Data|array $data): self return $self; } + /** + * Indicates whether the request was successful. + */ public function withSuccess(bool $success): self { $self = clone $this; diff --git a/src/Sessions/SessionNavigateResponse.php b/src/Sessions/SessionNavigateResponse.php index de02d0e..a918959 100644 --- a/src/Sessions/SessionNavigateResponse.php +++ b/src/Sessions/SessionNavigateResponse.php @@ -24,6 +24,9 @@ final class SessionNavigateResponse implements BaseModel #[Required] public Data $data; + /** + * Indicates whether the request was successful. + */ #[Required] public bool $success; @@ -74,6 +77,9 @@ public function withData(Data|array $data): self return $self; } + /** + * Indicates whether the request was successful. + */ public function withSuccess(bool $success): self { $self = clone $this; diff --git a/src/Sessions/SessionObserveResponse.php b/src/Sessions/SessionObserveResponse.php index 7e6a282..fa53508 100644 --- a/src/Sessions/SessionObserveResponse.php +++ b/src/Sessions/SessionObserveResponse.php @@ -24,6 +24,9 @@ final class SessionObserveResponse implements BaseModel #[Required] public Data $data; + /** + * Indicates whether the request was successful. + */ #[Required] public bool $success; @@ -74,6 +77,9 @@ public function withData(Data|array $data): self return $self; } + /** + * Indicates whether the request was successful. + */ public function withSuccess(bool $success): self { $self = clone $this; diff --git a/src/Sessions/SessionStartParams.php b/src/Sessions/SessionStartParams.php index 79c3fce..06273b7 100644 --- a/src/Sessions/SessionStartParams.php +++ b/src/Sessions/SessionStartParams.php @@ -33,7 +33,7 @@ * experimental?: bool|null, * selfHeal?: bool|null, * systemPrompt?: string|null, - * verbose?: float|null, + * verbose?: int|null, * waitForCaptchaSolves?: bool|null, * xLanguage?: null|XLanguage|value-of, * xSDKVersion?: string|null, @@ -99,7 +99,7 @@ final class SessionStartParams implements BaseModel * Logging verbosity level (0=quiet, 1=normal, 2=debug). */ #[Optional] - public ?float $verbose; + public ?int $verbose; #[Optional] public ?bool $waitForCaptchaSolves; @@ -172,7 +172,7 @@ public static function with( ?bool $experimental = null, ?bool $selfHeal = null, ?string $systemPrompt = null, - ?float $verbose = null, + ?int $verbose = null, ?bool $waitForCaptchaSolves = null, XLanguage|string|null $xLanguage = null, ?string $xSDKVersion = null, @@ -310,7 +310,7 @@ public function withSystemPrompt(string $systemPrompt): self /** * Logging verbosity level (0=quiet, 1=normal, 2=debug). */ - public function withVerbose(float $verbose): self + public function withVerbose(int $verbose): self { $self = clone $this; $self['verbose'] = $verbose; diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig.php index 4d4b609..54cb42b 100644 --- a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig.php +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig.php @@ -9,13 +9,12 @@ use Stagehand\Core\Concerns\SdkModel; use Stagehand\Core\Contracts\BaseModel; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\UnionMember1\BrowserbaseProxyConfig\Geolocation; -use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\UnionMember1\BrowserbaseProxyConfig\Type; /** * @phpstan-import-type GeolocationShape from \Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\UnionMember1\BrowserbaseProxyConfig\Geolocation * * @phpstan-type BrowserbaseProxyConfigShape = array{ - * type: Type|value-of, + * type: 'browserbase', * domainPattern?: string|null, * geolocation?: null|Geolocation|GeolocationShape, * } @@ -25,9 +24,9 @@ final class BrowserbaseProxyConfig implements BaseModel /** @use SdkModel */ use SdkModel; - /** @var value-of $type */ - #[Required(enum: Type::class)] - public string $type; + /** @var 'browserbase' $type */ + #[Required] + public string $type = 'browserbase'; #[Optional] public ?string $domainPattern; @@ -35,20 +34,6 @@ final class BrowserbaseProxyConfig implements BaseModel #[Optional] public ?Geolocation $geolocation; - /** - * `new BrowserbaseProxyConfig()` is missing required properties by the API. - * - * To enforce required parameters use - * ``` - * BrowserbaseProxyConfig::with(type: ...) - * ``` - * - * Otherwise ensure the following setters are called - * - * ``` - * (new BrowserbaseProxyConfig)->withType(...) - * ``` - */ public function __construct() { $this->initialize(); @@ -59,35 +44,20 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param Type|value-of $type * @param GeolocationShape $geolocation */ public static function with( - Type|string $type, ?string $domainPattern = null, - Geolocation|array|null $geolocation = null, + Geolocation|array|null $geolocation = null ): self { $self = new self; - $self['type'] = $type; - null !== $domainPattern && $self['domainPattern'] = $domainPattern; null !== $geolocation && $self['geolocation'] = $geolocation; return $self; } - /** - * @param Type|value-of $type - */ - public function withType(Type|string $type): self - { - $self = clone $this; - $self['type'] = $type; - - return $self; - } - public function withDomainPattern(string $domainPattern): self { $self = clone $this; diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig/Type.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig/Type.php deleted file mode 100644 index 32496f9..0000000 --- a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig/Type.php +++ /dev/null @@ -1,10 +0,0 @@ -, + * type: 'external', * domainPattern?: string|null, * password?: string|null, * username?: string|null, @@ -24,12 +23,12 @@ final class ExternalProxyConfig implements BaseModel /** @use SdkModel */ use SdkModel; + /** @var 'external' $type */ #[Required] - public string $server; + public string $type = 'external'; - /** @var value-of $type */ - #[Required(enum: Type::class)] - public string $type; + #[Required] + public string $server; #[Optional] public ?string $domainPattern; @@ -45,13 +44,13 @@ final class ExternalProxyConfig implements BaseModel * * To enforce required parameters use * ``` - * ExternalProxyConfig::with(server: ..., type: ...) + * ExternalProxyConfig::with(server: ...) * ``` * * Otherwise ensure the following setters are called * * ``` - * (new ExternalProxyConfig)->withServer(...)->withType(...) + * (new ExternalProxyConfig)->withServer(...) * ``` */ public function __construct() @@ -63,12 +62,9 @@ public function __construct() * Construct an instance from the required parameters. * * You must use named parameters to construct any parameters with a default value. - * - * @param Type|value-of $type */ public static function with( string $server, - Type|string $type, ?string $domainPattern = null, ?string $password = null, ?string $username = null, @@ -76,7 +72,6 @@ public static function with( $self = new self; $self['server'] = $server; - $self['type'] = $type; null !== $domainPattern && $self['domainPattern'] = $domainPattern; null !== $password && $self['password'] = $password; @@ -93,17 +88,6 @@ public function withServer(string $server): self return $self; } - /** - * @param Type|value-of $type - */ - public function withType(Type|string $type): self - { - $self = clone $this; - $self['type'] = $type; - - return $self; - } - public function withDomainPattern(string $domainPattern): self { $self = clone $this; diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/ExternalProxyConfig/Type.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/ExternalProxyConfig/Type.php deleted file mode 100644 index dd4a6c6..0000000 --- a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/ExternalProxyConfig/Type.php +++ /dev/null @@ -1,10 +0,0 @@ - Date: Wed, 17 Dec 2025 18:56:41 +0000 Subject: [PATCH 11/29] feat(api): manual updates --- .stats.yml | 4 +- src/ServiceContracts/SessionsContract.php | 5 ++- src/Services/SessionsRawService.php | 3 +- src/Services/SessionsService.php | 5 ++- src/Sessions/ModelConfig.php | 10 +++-- ...UnionMember1.php => ModelConfigObject.php} | 30 ++++++++++++--- src/Sessions/SessionActParams/Options.php | 13 +++++-- src/Sessions/SessionEndResponse.php | 38 +++++++++++++++++-- .../SessionExecuteParams/AgentConfig.php | 13 +++++-- src/Sessions/SessionExtractParams/Options.php | 13 +++++-- src/Sessions/SessionObserveParams/Options.php | 13 +++++-- src/Sessions/SessionStartParams.php | 10 ++++- .../Proxies/UnionMember1.php | 10 ++++- src/Sessions/SessionStartParams/Verbose.php | 17 +++++++++ tests/Services/SessionsTest.php | 6 ++- 15 files changed, 149 insertions(+), 41 deletions(-) rename src/Sessions/ModelConfig/{UnionMember1.php => ModelConfigObject.php} (70%) create mode 100644 src/Sessions/SessionStartParams/Verbose.php diff --git a/.stats.yml b/.stats.yml index 08f0cef..38ef77c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-d571232203ef4e00986a3245224267db6f8aaffdad57780f712e0694dc8d9e37.yml -openapi_spec_hash: d5d635dd7b24a2e1255c6f2a895253ff +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-817d1d4e845b1946dac8ee10fd34b3f533aa36f74ac598582ffb1b0399a5a932.yml +openapi_spec_hash: 9d856db62b34909fec94743235b3d7be config_hash: 88e87ba7021be93d267ecfc8f5e6b891 diff --git a/src/ServiceContracts/SessionsContract.php b/src/ServiceContracts/SessionsContract.php index a2ed8b5..ef36f6f 100644 --- a/src/ServiceContracts/SessionsContract.php +++ b/src/ServiceContracts/SessionsContract.php @@ -21,6 +21,7 @@ use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\HTTPVersion; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\OperatingSystem; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Region; +use Stagehand\Sessions\SessionStartParams\Verbose; use Stagehand\Sessions\SessionStartResponse; interface SessionsContract @@ -270,7 +271,7 @@ public function observe( * @param bool $experimental Body param: * @param bool $selfHeal Body param: Enable self-healing for failed actions * @param string $systemPrompt Body param: Custom system prompt for AI operations - * @param int $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) + * @param 0|1|2|Verbose $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) * @param bool $waitForCaptchaSolves Body param: * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionStartParams\XLanguage $xLanguage Header param: Client SDK language * @param string $xSDKVersion Header param: Version of the Stagehand SDK @@ -290,7 +291,7 @@ public function start( ?bool $experimental = null, ?bool $selfHeal = null, ?string $systemPrompt = null, - ?int $verbose = null, + int|Verbose|null $verbose = null, ?bool $waitForCaptchaSolves = null, string|\Stagehand\Sessions\SessionStartParams\XLanguage|null $xLanguage = null, ?string $xSDKVersion = null, diff --git a/src/Services/SessionsRawService.php b/src/Services/SessionsRawService.php index 484541d..379e397 100644 --- a/src/Services/SessionsRawService.php +++ b/src/Services/SessionsRawService.php @@ -29,6 +29,7 @@ use Stagehand\Sessions\SessionStartParams\Browser\Type; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\HTTPVersion; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Region; +use Stagehand\Sessions\SessionStartParams\Verbose; use Stagehand\Sessions\SessionStartResponse; final class SessionsRawService implements SessionsRawContract @@ -444,7 +445,7 @@ public function observe( * experimental?: bool, * selfHeal?: bool, * systemPrompt?: string, - * verbose?: int, + * verbose?: 0|1|2|Verbose, * waitForCaptchaSolves?: bool, * xLanguage?: 'typescript'|'python'|'playground'|SessionStartParams\XLanguage, * xSDKVersion?: string, diff --git a/src/Services/SessionsService.php b/src/Services/SessionsService.php index 05a4fcc..95d0290 100644 --- a/src/Services/SessionsService.php +++ b/src/Services/SessionsService.php @@ -24,6 +24,7 @@ use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\HTTPVersion; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\OperatingSystem; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Region; +use Stagehand\Sessions\SessionStartParams\Verbose; use Stagehand\Sessions\SessionStartResponse; final class SessionsService implements SessionsContract @@ -400,7 +401,7 @@ public function observe( * @param bool $experimental Body param: * @param bool $selfHeal Body param: Enable self-healing for failed actions * @param string $systemPrompt Body param: Custom system prompt for AI operations - * @param int $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) + * @param 0|1|2|Verbose $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) * @param bool $waitForCaptchaSolves Body param: * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionStartParams\XLanguage $xLanguage Header param: Client SDK language * @param string $xSDKVersion Header param: Version of the Stagehand SDK @@ -420,7 +421,7 @@ public function start( ?bool $experimental = null, ?bool $selfHeal = null, ?string $systemPrompt = null, - ?int $verbose = null, + int|Verbose|null $verbose = null, ?bool $waitForCaptchaSolves = null, string|\Stagehand\Sessions\SessionStartParams\XLanguage|null $xLanguage = null, ?string $xSDKVersion = null, diff --git a/src/Sessions/ModelConfig.php b/src/Sessions/ModelConfig.php index af40bc4..86c9dfd 100644 --- a/src/Sessions/ModelConfig.php +++ b/src/Sessions/ModelConfig.php @@ -7,12 +7,14 @@ use Stagehand\Core\Concerns\SdkUnion; use Stagehand\Core\Conversion\Contracts\Converter; use Stagehand\Core\Conversion\Contracts\ConverterSource; -use Stagehand\Sessions\ModelConfig\UnionMember1; +use Stagehand\Sessions\ModelConfig\ModelConfigObject; /** - * @phpstan-import-type UnionMember1Shape from \Stagehand\Sessions\ModelConfig\UnionMember1 + * Model name string with provider prefix (e.g., 'openai/gpt-5-nano', 'anthropic/claude-4.5-opus'). * - * @phpstan-type ModelConfigShape = string|UnionMember1Shape + * @phpstan-import-type ModelConfigObjectShape from \Stagehand\Sessions\ModelConfig\ModelConfigObject + * + * @phpstan-type ModelConfigShape = string|ModelConfigObjectShape */ final class ModelConfig implements ConverterSource { @@ -23,6 +25,6 @@ final class ModelConfig implements ConverterSource */ public static function variants(): array { - return ['string', UnionMember1::class]; + return ['string', ModelConfigObject::class]; } } diff --git a/src/Sessions/ModelConfig/UnionMember1.php b/src/Sessions/ModelConfig/ModelConfigObject.php similarity index 70% rename from src/Sessions/ModelConfig/UnionMember1.php rename to src/Sessions/ModelConfig/ModelConfigObject.php index 7128c3c..f96da53 100644 --- a/src/Sessions/ModelConfig/UnionMember1.php +++ b/src/Sessions/ModelConfig/ModelConfigObject.php @@ -10,36 +10,45 @@ use Stagehand\Core\Contracts\BaseModel; /** - * @phpstan-type UnionMember1Shape = array{ + * @phpstan-type ModelConfigObjectShape = array{ * modelName: string, apiKey?: string|null, baseURL?: string|null * } */ -final class UnionMember1 implements BaseModel +final class ModelConfigObject implements BaseModel { - /** @use SdkModel */ + /** @use SdkModel */ use SdkModel; + /** + * Model name string without prefix (e.g., 'gpt-5-nano', 'claude-4.5-opus'). + */ #[Required] public string $modelName; + /** + * API key for the model provider. + */ #[Optional] public ?string $apiKey; + /** + * Base URL for the model provider. + */ #[Optional] public ?string $baseURL; /** - * `new UnionMember1()` is missing required properties by the API. + * `new ModelConfigObject()` is missing required properties by the API. * * To enforce required parameters use * ``` - * UnionMember1::with(modelName: ...) + * ModelConfigObject::with(modelName: ...) * ``` * * Otherwise ensure the following setters are called * * ``` - * (new UnionMember1)->withModelName(...) + * (new ModelConfigObject)->withModelName(...) * ``` */ public function __construct() @@ -67,6 +76,9 @@ public static function with( return $self; } + /** + * Model name string without prefix (e.g., 'gpt-5-nano', 'claude-4.5-opus'). + */ public function withModelName(string $modelName): self { $self = clone $this; @@ -75,6 +87,9 @@ public function withModelName(string $modelName): self return $self; } + /** + * API key for the model provider. + */ public function withAPIKey(string $apiKey): self { $self = clone $this; @@ -83,6 +98,9 @@ public function withAPIKey(string $apiKey): self return $self; } + /** + * Base URL for the model provider. + */ public function withBaseURL(string $baseURL): self { $self = clone $this; diff --git a/src/Sessions/SessionActParams/Options.php b/src/Sessions/SessionActParams/Options.php index 0113bf2..9326579 100644 --- a/src/Sessions/SessionActParams/Options.php +++ b/src/Sessions/SessionActParams/Options.php @@ -7,7 +7,7 @@ use Stagehand\Core\Attributes\Optional; use Stagehand\Core\Concerns\SdkModel; use Stagehand\Core\Contracts\BaseModel; -use Stagehand\Sessions\ModelConfig\UnionMember1; +use Stagehand\Sessions\ModelConfig\ModelConfigObject; /** * @phpstan-import-type ModelConfigShape from \Stagehand\Sessions\ModelConfig @@ -23,8 +23,11 @@ final class Options implements BaseModel /** @use SdkModel */ use SdkModel; + /** + * Model name string with provider prefix (e.g., 'openai/gpt-5-nano', 'anthropic/claude-4.5-opus'). + */ #[Optional] - public string|UnionMember1|null $model; + public string|ModelConfigObject|null $model; /** * Timeout in ms for the action. @@ -54,7 +57,7 @@ public function __construct() * @param array $variables */ public static function with( - string|UnionMember1|array|null $model = null, + string|ModelConfigObject|array|null $model = null, ?float $timeout = null, ?array $variables = null, ): self { @@ -68,9 +71,11 @@ public static function with( } /** + * Model name string with provider prefix (e.g., 'openai/gpt-5-nano', 'anthropic/claude-4.5-opus'). + * * @param ModelConfigShape $model */ - public function withModel(string|UnionMember1|array $model): self + public function withModel(string|ModelConfigObject|array $model): self { $self = clone $this; $self['model'] = $model; diff --git a/src/Sessions/SessionEndResponse.php b/src/Sessions/SessionEndResponse.php index 8253d13..d8f0976 100644 --- a/src/Sessions/SessionEndResponse.php +++ b/src/Sessions/SessionEndResponse.php @@ -16,9 +16,26 @@ final class SessionEndResponse implements BaseModel /** @use SdkModel */ use SdkModel; + /** + * Indicates whether the request was successful. + */ #[Required] - public bool $success = true; + public bool $success; + /** + * `new SessionEndResponse()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * SessionEndResponse::with(success: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new SessionEndResponse)->withSuccess(...) + * ``` + */ public function __construct() { $this->initialize(); @@ -29,8 +46,23 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. */ - public static function with(): self + public static function with(bool $success): self { - return new self; + $self = new self; + + $self['success'] = $success; + + return $self; + } + + /** + * Indicates whether the request was successful. + */ + public function withSuccess(bool $success): self + { + $self = clone $this; + $self['success'] = $success; + + return $self; } } diff --git a/src/Sessions/SessionExecuteParams/AgentConfig.php b/src/Sessions/SessionExecuteParams/AgentConfig.php index 7fef271..54e981a 100644 --- a/src/Sessions/SessionExecuteParams/AgentConfig.php +++ b/src/Sessions/SessionExecuteParams/AgentConfig.php @@ -7,7 +7,7 @@ use Stagehand\Core\Attributes\Optional; use Stagehand\Core\Concerns\SdkModel; use Stagehand\Core\Contracts\BaseModel; -use Stagehand\Sessions\ModelConfig\UnionMember1; +use Stagehand\Sessions\ModelConfig\ModelConfigObject; /** * @phpstan-import-type ModelConfigShape from \Stagehand\Sessions\ModelConfig @@ -27,8 +27,11 @@ final class AgentConfig implements BaseModel #[Optional] public ?bool $cua; + /** + * Model name string with provider prefix (e.g., 'openai/gpt-5-nano', 'anthropic/claude-4.5-opus'). + */ #[Optional] - public string|UnionMember1|null $model; + public string|ModelConfigObject|null $model; /** * Custom system prompt for the agent. @@ -50,7 +53,7 @@ public function __construct() */ public static function with( ?bool $cua = null, - string|UnionMember1|array|null $model = null, + string|ModelConfigObject|array|null $model = null, ?string $systemPrompt = null, ): self { $self = new self; @@ -74,9 +77,11 @@ public function withCua(bool $cua): self } /** + * Model name string with provider prefix (e.g., 'openai/gpt-5-nano', 'anthropic/claude-4.5-opus'). + * * @param ModelConfigShape $model */ - public function withModel(string|UnionMember1|array $model): self + public function withModel(string|ModelConfigObject|array $model): self { $self = clone $this; $self['model'] = $model; diff --git a/src/Sessions/SessionExtractParams/Options.php b/src/Sessions/SessionExtractParams/Options.php index b437deb..18da4fd 100644 --- a/src/Sessions/SessionExtractParams/Options.php +++ b/src/Sessions/SessionExtractParams/Options.php @@ -7,7 +7,7 @@ use Stagehand\Core\Attributes\Optional; use Stagehand\Core\Concerns\SdkModel; use Stagehand\Core\Contracts\BaseModel; -use Stagehand\Sessions\ModelConfig\UnionMember1; +use Stagehand\Sessions\ModelConfig\ModelConfigObject; /** * @phpstan-import-type ModelConfigShape from \Stagehand\Sessions\ModelConfig @@ -21,8 +21,11 @@ final class Options implements BaseModel /** @use SdkModel */ use SdkModel; + /** + * Model name string with provider prefix (e.g., 'openai/gpt-5-nano', 'anthropic/claude-4.5-opus'). + */ #[Optional] - public string|UnionMember1|null $model; + public string|ModelConfigObject|null $model; /** * CSS selector to scope extraction to a specific element. @@ -49,7 +52,7 @@ public function __construct() * @param ModelConfigShape $model */ public static function with( - string|UnionMember1|array|null $model = null, + string|ModelConfigObject|array|null $model = null, ?string $selector = null, ?float $timeout = null, ): self { @@ -63,9 +66,11 @@ public static function with( } /** + * Model name string with provider prefix (e.g., 'openai/gpt-5-nano', 'anthropic/claude-4.5-opus'). + * * @param ModelConfigShape $model */ - public function withModel(string|UnionMember1|array $model): self + public function withModel(string|ModelConfigObject|array $model): self { $self = clone $this; $self['model'] = $model; diff --git a/src/Sessions/SessionObserveParams/Options.php b/src/Sessions/SessionObserveParams/Options.php index 767953c..f76bf82 100644 --- a/src/Sessions/SessionObserveParams/Options.php +++ b/src/Sessions/SessionObserveParams/Options.php @@ -7,7 +7,7 @@ use Stagehand\Core\Attributes\Optional; use Stagehand\Core\Concerns\SdkModel; use Stagehand\Core\Contracts\BaseModel; -use Stagehand\Sessions\ModelConfig\UnionMember1; +use Stagehand\Sessions\ModelConfig\ModelConfigObject; /** * @phpstan-import-type ModelConfigShape from \Stagehand\Sessions\ModelConfig @@ -21,8 +21,11 @@ final class Options implements BaseModel /** @use SdkModel */ use SdkModel; + /** + * Model name string with provider prefix (e.g., 'openai/gpt-5-nano', 'anthropic/claude-4.5-opus'). + */ #[Optional] - public string|UnionMember1|null $model; + public string|ModelConfigObject|null $model; /** * CSS selector to scope observation to a specific element. @@ -49,7 +52,7 @@ public function __construct() * @param ModelConfigShape $model */ public static function with( - string|UnionMember1|array|null $model = null, + string|ModelConfigObject|array|null $model = null, ?string $selector = null, ?float $timeout = null, ): self { @@ -63,9 +66,11 @@ public static function with( } /** + * Model name string with provider prefix (e.g., 'openai/gpt-5-nano', 'anthropic/claude-4.5-opus'). + * * @param ModelConfigShape $model */ - public function withModel(string|UnionMember1|array $model): self + public function withModel(string|ModelConfigObject|array $model): self { $self = clone $this; $self['model'] = $model; diff --git a/src/Sessions/SessionStartParams.php b/src/Sessions/SessionStartParams.php index 06273b7..7b9e2c4 100644 --- a/src/Sessions/SessionStartParams.php +++ b/src/Sessions/SessionStartParams.php @@ -11,6 +11,7 @@ use Stagehand\Core\Contracts\BaseModel; use Stagehand\Sessions\SessionStartParams\Browser; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams; +use Stagehand\Sessions\SessionStartParams\Verbose; use Stagehand\Sessions\SessionStartParams\XLanguage; use Stagehand\Sessions\SessionStartParams\XStreamResponse; @@ -33,7 +34,7 @@ * experimental?: bool|null, * selfHeal?: bool|null, * systemPrompt?: string|null, - * verbose?: int|null, + * verbose?: null|0|1|2, * waitForCaptchaSolves?: bool|null, * xLanguage?: null|XLanguage|value-of, * xSDKVersion?: string|null, @@ -97,8 +98,10 @@ final class SessionStartParams implements BaseModel /** * Logging verbosity level (0=quiet, 1=normal, 2=debug). + * + * @var 0|1|2|null $verbose */ - #[Optional] + #[Optional(enum: Verbose::class)] public ?int $verbose; #[Optional] @@ -158,6 +161,7 @@ public function __construct() * * @param BrowserShape $browser * @param BrowserbaseSessionCreateParamsShape $browserbaseSessionCreateParams + * @param 0|1|2 $verbose * @param XLanguage|value-of $xLanguage * @param XStreamResponse|value-of $xStreamResponse */ @@ -309,6 +313,8 @@ public function withSystemPrompt(string $systemPrompt): self /** * Logging verbosity level (0=quiet, 1=normal, 2=debug). + * + * @param 0|1|2 $verbose */ public function withVerbose(int $verbose): self { diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1.php index dcb373d..247be42 100644 --- a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1.php +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1.php @@ -20,11 +20,19 @@ final class UnionMember1 implements ConverterSource { use SdkUnion; + public static function discriminator(): string + { + return 'type'; + } + /** * @return list|array */ public static function variants(): array { - return [BrowserbaseProxyConfig::class, ExternalProxyConfig::class]; + return [ + 'browserbase' => BrowserbaseProxyConfig::class, + 'external' => ExternalProxyConfig::class, + ]; } } diff --git a/src/Sessions/SessionStartParams/Verbose.php b/src/Sessions/SessionStartParams/Verbose.php new file mode 100644 index 0000000..a3f9eff --- /dev/null +++ b/src/Sessions/SessionStartParams/Verbose.php @@ -0,0 +1,17 @@ + 'string', + 'model' => 'openai/gpt-5-nano', 'timeout' => 30000, 'variables' => ['username' => 'john_doe'], ], @@ -124,7 +124,9 @@ public function testExecuteWithOptionalParams(): void $result = $this->client->sessions->execute( 'c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123', agentConfig: [ - 'cua' => true, 'model' => 'string', 'systemPrompt' => 'systemPrompt', + 'cua' => true, + 'model' => 'openai/gpt-5-nano', + 'systemPrompt' => 'systemPrompt', ], executeOptions: [ 'instruction' => 'Log in with username \'demo\' and password \'test123\', then navigate to settings', From 7214304ca1bc4c954cc7519dc509ff085f94b77a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 19:06:59 +0000 Subject: [PATCH 12/29] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 38ef77c..65bd734 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-817d1d4e845b1946dac8ee10fd34b3f533aa36f74ac598582ffb1b0399a5a932.yml -openapi_spec_hash: 9d856db62b34909fec94743235b3d7be +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-e09ad013e10b6a6bb76dd9b2067696ba92bd7acb862b39bbfe2f296ebdb6eddf.yml +openapi_spec_hash: 2f633591561e4737534842273441a818 config_hash: 88e87ba7021be93d267ecfc8f5e6b891 From bbf28250640bcdeaf02f2a40ef93802d7630990d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 20:09:40 +0000 Subject: [PATCH 13/29] feat(api): manual updates --- .stats.yml | 6 +++--- src/ServiceContracts/SessionsContract.php | 5 ++--- src/Services/SessionsRawService.php | 3 +-- src/Services/SessionsService.php | 5 ++--- src/Sessions/SessionStartParams.php | 10 ++-------- .../BrowserbaseSessionCreateParams.php | 4 ++-- .../BrowserbaseSessionCreateParams/Proxies.php | 8 ++++---- .../{UnionMember1.php => ProxyConfigList.php} | 12 ++++++------ .../BrowserbaseProxyConfig.php | 6 +++--- .../BrowserbaseProxyConfig/Geolocation.php | 2 +- .../ExternalProxyConfig.php | 2 +- src/Sessions/SessionStartParams/Verbose.php | 17 ----------------- tests/Services/SessionsTest.php | 8 ++++---- 13 files changed, 31 insertions(+), 57 deletions(-) rename src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/{UnionMember1.php => ProxyConfigList.php} (75%) rename src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/{UnionMember1 => ProxyConfigList}/BrowserbaseProxyConfig.php (89%) rename src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/{UnionMember1 => ProxyConfigList}/BrowserbaseProxyConfig/Geolocation.php (96%) rename src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/{UnionMember1 => ProxyConfigList}/ExternalProxyConfig.php (98%) delete mode 100644 src/Sessions/SessionStartParams/Verbose.php diff --git a/.stats.yml b/.stats.yml index 65bd734..604325f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-e09ad013e10b6a6bb76dd9b2067696ba92bd7acb862b39bbfe2f296ebdb6eddf.yml -openapi_spec_hash: 2f633591561e4737534842273441a818 -config_hash: 88e87ba7021be93d267ecfc8f5e6b891 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-e96507dd78e76fccc77ba7fb09704da127ead6f4d73ea854e9b2150e90787ff4.yml +openapi_spec_hash: 0c2548b8fdd6de6789b19123e69609c1 +config_hash: c3abb41dbe698d59b3bf12f393013d54 diff --git a/src/ServiceContracts/SessionsContract.php b/src/ServiceContracts/SessionsContract.php index ef36f6f..a2ed8b5 100644 --- a/src/ServiceContracts/SessionsContract.php +++ b/src/ServiceContracts/SessionsContract.php @@ -21,7 +21,6 @@ use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\HTTPVersion; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\OperatingSystem; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Region; -use Stagehand\Sessions\SessionStartParams\Verbose; use Stagehand\Sessions\SessionStartResponse; interface SessionsContract @@ -271,7 +270,7 @@ public function observe( * @param bool $experimental Body param: * @param bool $selfHeal Body param: Enable self-healing for failed actions * @param string $systemPrompt Body param: Custom system prompt for AI operations - * @param 0|1|2|Verbose $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) + * @param int $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) * @param bool $waitForCaptchaSolves Body param: * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionStartParams\XLanguage $xLanguage Header param: Client SDK language * @param string $xSDKVersion Header param: Version of the Stagehand SDK @@ -291,7 +290,7 @@ public function start( ?bool $experimental = null, ?bool $selfHeal = null, ?string $systemPrompt = null, - int|Verbose|null $verbose = null, + ?int $verbose = null, ?bool $waitForCaptchaSolves = null, string|\Stagehand\Sessions\SessionStartParams\XLanguage|null $xLanguage = null, ?string $xSDKVersion = null, diff --git a/src/Services/SessionsRawService.php b/src/Services/SessionsRawService.php index 379e397..484541d 100644 --- a/src/Services/SessionsRawService.php +++ b/src/Services/SessionsRawService.php @@ -29,7 +29,6 @@ use Stagehand\Sessions\SessionStartParams\Browser\Type; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\HTTPVersion; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Region; -use Stagehand\Sessions\SessionStartParams\Verbose; use Stagehand\Sessions\SessionStartResponse; final class SessionsRawService implements SessionsRawContract @@ -445,7 +444,7 @@ public function observe( * experimental?: bool, * selfHeal?: bool, * systemPrompt?: string, - * verbose?: 0|1|2|Verbose, + * verbose?: int, * waitForCaptchaSolves?: bool, * xLanguage?: 'typescript'|'python'|'playground'|SessionStartParams\XLanguage, * xSDKVersion?: string, diff --git a/src/Services/SessionsService.php b/src/Services/SessionsService.php index 95d0290..05a4fcc 100644 --- a/src/Services/SessionsService.php +++ b/src/Services/SessionsService.php @@ -24,7 +24,6 @@ use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\HTTPVersion; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\OperatingSystem; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Region; -use Stagehand\Sessions\SessionStartParams\Verbose; use Stagehand\Sessions\SessionStartResponse; final class SessionsService implements SessionsContract @@ -401,7 +400,7 @@ public function observe( * @param bool $experimental Body param: * @param bool $selfHeal Body param: Enable self-healing for failed actions * @param string $systemPrompt Body param: Custom system prompt for AI operations - * @param 0|1|2|Verbose $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) + * @param int $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) * @param bool $waitForCaptchaSolves Body param: * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionStartParams\XLanguage $xLanguage Header param: Client SDK language * @param string $xSDKVersion Header param: Version of the Stagehand SDK @@ -421,7 +420,7 @@ public function start( ?bool $experimental = null, ?bool $selfHeal = null, ?string $systemPrompt = null, - int|Verbose|null $verbose = null, + ?int $verbose = null, ?bool $waitForCaptchaSolves = null, string|\Stagehand\Sessions\SessionStartParams\XLanguage|null $xLanguage = null, ?string $xSDKVersion = null, diff --git a/src/Sessions/SessionStartParams.php b/src/Sessions/SessionStartParams.php index 7b9e2c4..06273b7 100644 --- a/src/Sessions/SessionStartParams.php +++ b/src/Sessions/SessionStartParams.php @@ -11,7 +11,6 @@ use Stagehand\Core\Contracts\BaseModel; use Stagehand\Sessions\SessionStartParams\Browser; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams; -use Stagehand\Sessions\SessionStartParams\Verbose; use Stagehand\Sessions\SessionStartParams\XLanguage; use Stagehand\Sessions\SessionStartParams\XStreamResponse; @@ -34,7 +33,7 @@ * experimental?: bool|null, * selfHeal?: bool|null, * systemPrompt?: string|null, - * verbose?: null|0|1|2, + * verbose?: int|null, * waitForCaptchaSolves?: bool|null, * xLanguage?: null|XLanguage|value-of, * xSDKVersion?: string|null, @@ -98,10 +97,8 @@ final class SessionStartParams implements BaseModel /** * Logging verbosity level (0=quiet, 1=normal, 2=debug). - * - * @var 0|1|2|null $verbose */ - #[Optional(enum: Verbose::class)] + #[Optional] public ?int $verbose; #[Optional] @@ -161,7 +158,6 @@ public function __construct() * * @param BrowserShape $browser * @param BrowserbaseSessionCreateParamsShape $browserbaseSessionCreateParams - * @param 0|1|2 $verbose * @param XLanguage|value-of $xLanguage * @param XStreamResponse|value-of $xStreamResponse */ @@ -313,8 +309,6 @@ public function withSystemPrompt(string $systemPrompt): self /** * Logging verbosity level (0=quiet, 1=normal, 2=debug). - * - * @param 0|1|2 $verbose */ public function withVerbose(int $verbose): self { diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams.php index 2e07f34..60cbb6b 100644 --- a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams.php +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams.php @@ -9,8 +9,8 @@ use Stagehand\Core\Contracts\BaseModel; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies; -use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\UnionMember1\BrowserbaseProxyConfig; -use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\UnionMember1\ExternalProxyConfig; +use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\ProxyConfigList\BrowserbaseProxyConfig; +use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\ProxyConfigList\ExternalProxyConfig; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Region; /** diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies.php index 460a137..2b16438 100644 --- a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies.php +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies.php @@ -8,12 +8,12 @@ use Stagehand\Core\Conversion\Contracts\Converter; use Stagehand\Core\Conversion\Contracts\ConverterSource; use Stagehand\Core\Conversion\ListOf; -use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\UnionMember1; +use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\ProxyConfigList; /** - * @phpstan-import-type UnionMember1Shape from \Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\UnionMember1 + * @phpstan-import-type ProxyConfigListShape from \Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\ProxyConfigList * - * @phpstan-type ProxiesShape = bool|list + * @phpstan-type ProxiesShape = bool|list */ final class Proxies implements ConverterSource { @@ -24,6 +24,6 @@ final class Proxies implements ConverterSource */ public static function variants(): array { - return ['bool', new ListOf(UnionMember1::class)]; + return ['bool', new ListOf(ProxyConfigList::class)]; } } diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/ProxyConfigList.php similarity index 75% rename from src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1.php rename to src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/ProxyConfigList.php index 247be42..6462c66 100644 --- a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1.php +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/ProxyConfigList.php @@ -7,16 +7,16 @@ use Stagehand\Core\Concerns\SdkUnion; use Stagehand\Core\Conversion\Contracts\Converter; use Stagehand\Core\Conversion\Contracts\ConverterSource; -use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\UnionMember1\BrowserbaseProxyConfig; -use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\UnionMember1\ExternalProxyConfig; +use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\ProxyConfigList\BrowserbaseProxyConfig; +use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\ProxyConfigList\ExternalProxyConfig; /** - * @phpstan-import-type BrowserbaseProxyConfigShape from \Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\UnionMember1\BrowserbaseProxyConfig - * @phpstan-import-type ExternalProxyConfigShape from \Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\UnionMember1\ExternalProxyConfig + * @phpstan-import-type BrowserbaseProxyConfigShape from \Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\ProxyConfigList\BrowserbaseProxyConfig + * @phpstan-import-type ExternalProxyConfigShape from \Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\ProxyConfigList\ExternalProxyConfig * - * @phpstan-type UnionMember1Shape = BrowserbaseProxyConfigShape|ExternalProxyConfigShape + * @phpstan-type ProxyConfigListShape = BrowserbaseProxyConfigShape|ExternalProxyConfigShape */ -final class UnionMember1 implements ConverterSource +final class ProxyConfigList implements ConverterSource { use SdkUnion; diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/ProxyConfigList/BrowserbaseProxyConfig.php similarity index 89% rename from src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig.php rename to src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/ProxyConfigList/BrowserbaseProxyConfig.php index 54cb42b..c939391 100644 --- a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig.php +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/ProxyConfigList/BrowserbaseProxyConfig.php @@ -2,16 +2,16 @@ declare(strict_types=1); -namespace Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\UnionMember1; +namespace Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\ProxyConfigList; use Stagehand\Core\Attributes\Optional; use Stagehand\Core\Attributes\Required; use Stagehand\Core\Concerns\SdkModel; use Stagehand\Core\Contracts\BaseModel; -use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\UnionMember1\BrowserbaseProxyConfig\Geolocation; +use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\ProxyConfigList\BrowserbaseProxyConfig\Geolocation; /** - * @phpstan-import-type GeolocationShape from \Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\UnionMember1\BrowserbaseProxyConfig\Geolocation + * @phpstan-import-type GeolocationShape from \Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\ProxyConfigList\BrowserbaseProxyConfig\Geolocation * * @phpstan-type BrowserbaseProxyConfigShape = array{ * type: 'browserbase', diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig/Geolocation.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/ProxyConfigList/BrowserbaseProxyConfig/Geolocation.php similarity index 96% rename from src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig/Geolocation.php rename to src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/ProxyConfigList/BrowserbaseProxyConfig/Geolocation.php index 93deda1..0bfd18e 100644 --- a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/BrowserbaseProxyConfig/Geolocation.php +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/ProxyConfigList/BrowserbaseProxyConfig/Geolocation.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\UnionMember1\BrowserbaseProxyConfig; +namespace Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\ProxyConfigList\BrowserbaseProxyConfig; use Stagehand\Core\Attributes\Optional; use Stagehand\Core\Attributes\Required; diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/ExternalProxyConfig.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/ProxyConfigList/ExternalProxyConfig.php similarity index 98% rename from src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/ExternalProxyConfig.php rename to src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/ProxyConfigList/ExternalProxyConfig.php index da6e9ef..a203e40 100644 --- a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/UnionMember1/ExternalProxyConfig.php +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/ProxyConfigList/ExternalProxyConfig.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\UnionMember1; +namespace Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Proxies\ProxyConfigList; use Stagehand\Core\Attributes\Optional; use Stagehand\Core\Attributes\Required; diff --git a/src/Sessions/SessionStartParams/Verbose.php b/src/Sessions/SessionStartParams/Verbose.php deleted file mode 100644 index a3f9eff..0000000 --- a/src/Sessions/SessionStartParams/Verbose.php +++ /dev/null @@ -1,17 +0,0 @@ - Date: Thu, 18 Dec 2025 01:39:33 +0000 Subject: [PATCH 14/29] feat(api): manual updates --- .stats.yml | 6 +- README.md | 4 +- src/Core/Concerns/SdkStream.php | 57 ++++ src/Core/Implementation/IteratorExit.php | 5 + src/SSEStream.php | 77 +++++ src/ServiceContracts/SessionsContract.php | 146 ++++++++- src/ServiceContracts/SessionsRawContract.php | 66 +++++ src/Services/SessionsRawService.php | 279 +++++++++++++++++- src/Services/SessionsService.php | 216 +++++++++++++- src/Sessions/SessionActParams.php | 7 +- src/Sessions/SessionActParams/Input.php | 8 +- .../SessionActParams/Input/ActionInput.php | 141 --------- src/Sessions/SessionNavigateParams.php | 20 ++ src/Sessions/SessionStartResponse/Data.php | 37 ++- src/Sessions/StreamEvent.php | 123 ++++++++ src/Sessions/StreamEvent/Data.php | 32 ++ .../Data/StreamEventLogDataOutput.php | 74 +++++ .../Data/StreamEventSystemDataOutput.php | 118 ++++++++ .../StreamEventSystemDataOutput/Status.php | 21 ++ src/Sessions/StreamEvent/Type.php | 15 + tests/Services/SessionsTest.php | 1 + 21 files changed, 1281 insertions(+), 172 deletions(-) create mode 100644 src/Core/Concerns/SdkStream.php create mode 100644 src/Core/Implementation/IteratorExit.php create mode 100644 src/SSEStream.php delete mode 100644 src/Sessions/SessionActParams/Input/ActionInput.php create mode 100644 src/Sessions/StreamEvent.php create mode 100644 src/Sessions/StreamEvent/Data.php create mode 100644 src/Sessions/StreamEvent/Data/StreamEventLogDataOutput.php create mode 100644 src/Sessions/StreamEvent/Data/StreamEventSystemDataOutput.php create mode 100644 src/Sessions/StreamEvent/Data/StreamEventSystemDataOutput/Status.php create mode 100644 src/Sessions/StreamEvent/Type.php diff --git a/.stats.yml b/.stats.yml index 604325f..5dba58c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-e96507dd78e76fccc77ba7fb09704da127ead6f4d73ea854e9b2150e90787ff4.yml -openapi_spec_hash: 0c2548b8fdd6de6789b19123e69609c1 -config_hash: c3abb41dbe698d59b3bf12f393013d54 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-f7d6b6489159f611a2bfdc267ce0a6fc0455bed1ffa0c310044baaa5d8381b9b.yml +openapi_spec_hash: cd88d8068abfde8382da0bed674e440c +config_hash: 5c69fb596588b8ace08203858518c149 diff --git a/README.md b/README.md index 397b274..f15bb6c 100644 --- a/README.md +++ b/README.md @@ -65,10 +65,10 @@ var_dump($response->data); ### Value Objects -It is recommended to use the static `with` constructor `Dog::with(name: "Joey")` +It is recommended to use the static `with` constructor `Action::with(description: 'Click the submit button', ...)` and named parameters to initialize value objects. -However, builders are also provided `(new Dog)->withName("Joey")`. +However, builders are also provided `(new Action)->withDescription('Click the submit button')`. ### Handling errors diff --git a/src/Core/Concerns/SdkStream.php b/src/Core/Concerns/SdkStream.php new file mode 100644 index 0000000..4af482b --- /dev/null +++ b/src/Core/Concerns/SdkStream.php @@ -0,0 +1,57 @@ + + */ +trait SdkStream +{ + /** @var \Generator */ + protected \Generator $stream; + + /** @var \Generator */ + private \Generator $generator; + + public function __construct( + protected string|Converter|ConverterSource $convert, + protected RequestInterface $request, + protected ResponseInterface $response, + protected mixed $parsedBody, + ) { + // @phpstan-ignore-next-line + $this->stream = $parsedBody; + $this->generator = $this->parsedGenerator(); + } + + /** @return \Iterator */ + public function getIterator(): \Iterator + { + return $this->generator; + } + + public function close(): void + { + try { + $this->stream->throw(new IteratorExit); + } catch (IteratorExit $_) { + // IteratorExit shouldn't be noticed. + return; + } + } + + /** @return \Generator $stream */ + abstract private function parsedGenerator(): \Generator; +} diff --git a/src/Core/Implementation/IteratorExit.php b/src/Core/Implementation/IteratorExit.php new file mode 100644 index 0000000..483976e --- /dev/null +++ b/src/Core/Implementation/IteratorExit.php @@ -0,0 +1,5 @@ + + */ +final class SSEStream implements BaseStream +{ + /** + * @use SdkStream + */ + use SdkStream; + + private function parsedGenerator(): \Generator + { + if (!$this->stream->valid()) { + return; + } + + $done = false; + foreach ($this->stream as $row) { + // @phpstan-ignore if.alwaysFalse + if ($done) { + // Iterate through the whole stream + continue; + } + + switch ($row['event'] ?? null) { + case null: + if ($data = $row['data'] ?? '') { + $decoded = Util::decodeJson($data); + + yield Conversion::coerce($this->convert, value: $decoded); + } + + break; + } + + if ($data = $row['data'] ?? '') { + if (str_starts_with($data, needle: 'finished')) { + $done = true; + + continue; + } + + if (str_starts_with($data, needle: 'error')) { + if ($data = $row['data'] ?? '') { + $json = Util::decodeJson($data); + $message = Util::prettyEncodeJson($json); + + $exn = APIStatusException::from( + request: $this->request, + response: $this->response, + message: $message, + ); + + throw $exn; + } + + continue; + } + } + } + } +} diff --git a/src/ServiceContracts/SessionsContract.php b/src/ServiceContracts/SessionsContract.php index a2ed8b5..91e4699 100644 --- a/src/ServiceContracts/SessionsContract.php +++ b/src/ServiceContracts/SessionsContract.php @@ -4,8 +4,10 @@ namespace Stagehand\ServiceContracts; +use Stagehand\Core\Contracts\BaseStream; use Stagehand\Core\Exceptions\APIException; use Stagehand\RequestOptions; +use Stagehand\Sessions\Action; use Stagehand\Sessions\SessionActParams\XLanguage; use Stagehand\Sessions\SessionActParams\XStreamResponse; use Stagehand\Sessions\SessionActResponse; @@ -22,6 +24,7 @@ use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\OperatingSystem; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Region; use Stagehand\Sessions\SessionStartResponse; +use Stagehand\Sessions\StreamEvent; interface SessionsContract { @@ -34,7 +37,7 @@ interface SessionsContract * selector: string, * arguments?: list, * method?: string, - * } $input Body param: Natural language instruction or Action object + * }|Action $input Body param: Natural language instruction or Action object * @param string $frameID Body param: Target frame ID for the action * @param array{ * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, @@ -50,7 +53,7 @@ interface SessionsContract */ public function act( string $id, - string|array $input, + string|array|Action $input, ?string $frameID = null, ?array $options = null, string|XLanguage|null $xLanguage = null, @@ -60,6 +63,43 @@ public function act( ?RequestOptions $requestOptions = null, ): SessionActResponse; + /** + * @api + * + * @param string $id Path param: Unique session identifier + * @param string|array{ + * description: string, + * selector: string, + * arguments?: list, + * method?: string, + * }|Action $input Body param: Natural language instruction or Action object + * @param string $frameID Body param: Target frame ID for the action + * @param array{ + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * timeout?: float, + * variables?: array, + * } $options Body param: + * @param 'typescript'|'python'|'playground'|XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE + * + * @return BaseStream + * + * @throws APIException + */ + public function actStream( + string $id, + string|array|Action $input, + ?string $frameID = null, + ?array $options = null, + string|XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|XStreamResponse|null $xStreamResponse = null, + ?RequestOptions $requestOptions = null, + ): BaseStream; + /** * @api * @@ -112,6 +152,40 @@ public function execute( ?RequestOptions $requestOptions = null, ): SessionExecuteResponse; + /** + * @api + * + * @param string $id Path param: Unique session identifier + * @param array{ + * cua?: bool, + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * systemPrompt?: string, + * } $agentConfig Body param: + * @param array{ + * instruction: string, highlightCursor?: bool, maxSteps?: float + * } $executeOptions Body param: + * @param string $frameID Body param: Target frame ID for the agent + * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionExecuteParams\XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|\Stagehand\Sessions\SessionExecuteParams\XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE + * + * @return BaseStream + * + * @throws APIException + */ + public function executeStream( + string $id, + array $agentConfig, + array $executeOptions, + ?string $frameID = null, + string|\Stagehand\Sessions\SessionExecuteParams\XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|\Stagehand\Sessions\SessionExecuteParams\XStreamResponse|null $xStreamResponse = null, + ?RequestOptions $requestOptions = null, + ): BaseStream; + /** * @api * @@ -144,6 +218,40 @@ public function extract( ?RequestOptions $requestOptions = null, ): SessionExtractResponse; + /** + * @api + * + * @param string $id Path param: Unique session identifier + * @param string $frameID Body param: Target frame ID for the extraction + * @param string $instruction Body param: Natural language instruction for what to extract + * @param array{ + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * selector?: string, + * timeout?: float, + * } $options Body param: + * @param array $schema Body param: JSON Schema defining the structure of data to extract + * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionExtractParams\XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|\Stagehand\Sessions\SessionExtractParams\XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE + * + * @return BaseStream + * + * @throws APIException + */ + public function extractStream( + string $id, + ?string $frameID = null, + ?string $instruction = null, + ?array $options = null, + ?array $schema = null, + string|\Stagehand\Sessions\SessionExtractParams\XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|\Stagehand\Sessions\SessionExtractParams\XStreamResponse|null $xStreamResponse = null, + ?RequestOptions $requestOptions = null, + ): BaseStream; + /** * @api * @@ -155,6 +263,7 @@ public function extract( * timeout?: float, * waitUntil?: 'load'|'domcontentloaded'|'networkidle'|WaitUntil, * } $options Body param: + * @param bool $streamResponse Body param: Whether to stream the response via SSE * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionNavigateParams\XLanguage $xLanguage Header param: Client SDK language * @param string $xSDKVersion Header param: Version of the Stagehand SDK * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent @@ -167,6 +276,7 @@ public function navigate( string $url, ?string $frameID = null, ?array $options = null, + ?bool $streamResponse = null, string|\Stagehand\Sessions\SessionNavigateParams\XLanguage|null $xLanguage = null, ?string $xSDKVersion = null, string|\DateTimeInterface|null $xSentAt = null, @@ -204,6 +314,38 @@ public function observe( ?RequestOptions $requestOptions = null, ): SessionObserveResponse; + /** + * @api + * + * @param string $id Path param: Unique session identifier + * @param string $frameID Body param: Target frame ID for the observation + * @param string $instruction Body param: Natural language instruction for what actions to find + * @param array{ + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * selector?: string, + * timeout?: float, + * } $options Body param: + * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionObserveParams\XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|\Stagehand\Sessions\SessionObserveParams\XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE + * + * @return BaseStream + * + * @throws APIException + */ + public function observeStream( + string $id, + ?string $frameID = null, + ?string $instruction = null, + ?array $options = null, + string|\Stagehand\Sessions\SessionObserveParams\XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|\Stagehand\Sessions\SessionObserveParams\XStreamResponse|null $xStreamResponse = null, + ?RequestOptions $requestOptions = null, + ): BaseStream; + /** * @api * diff --git a/src/ServiceContracts/SessionsRawContract.php b/src/ServiceContracts/SessionsRawContract.php index acc8b5f..3051c3f 100644 --- a/src/ServiceContracts/SessionsRawContract.php +++ b/src/ServiceContracts/SessionsRawContract.php @@ -5,6 +5,7 @@ namespace Stagehand\ServiceContracts; use Stagehand\Core\Contracts\BaseResponse; +use Stagehand\Core\Contracts\BaseStream; use Stagehand\Core\Exceptions\APIException; use Stagehand\RequestOptions; use Stagehand\Sessions\SessionActParams; @@ -21,6 +22,7 @@ use Stagehand\Sessions\SessionObserveResponse; use Stagehand\Sessions\SessionStartParams; use Stagehand\Sessions\SessionStartResponse; +use Stagehand\Sessions\StreamEvent; interface SessionsRawContract { @@ -40,6 +42,22 @@ public function act( ?RequestOptions $requestOptions = null, ): BaseResponse; + /** + * @api + * + * @param string $id Path param: Unique session identifier + * @param array|SessionActParams $params + * + * @return BaseResponse> + * + * @throws APIException + */ + public function actStream( + string $id, + array|SessionActParams $params, + ?RequestOptions $requestOptions = null, + ): BaseResponse; + /** * @api * @@ -72,6 +90,22 @@ public function execute( ?RequestOptions $requestOptions = null, ): BaseResponse; + /** + * @api + * + * @param string $id Path param: Unique session identifier + * @param array|SessionExecuteParams $params + * + * @return BaseResponse> + * + * @throws APIException + */ + public function executeStream( + string $id, + array|SessionExecuteParams $params, + ?RequestOptions $requestOptions = null, + ): BaseResponse; + /** * @api * @@ -88,6 +122,22 @@ public function extract( ?RequestOptions $requestOptions = null, ): BaseResponse; + /** + * @api + * + * @param string $id Path param: Unique session identifier + * @param array|SessionExtractParams $params + * + * @return BaseResponse> + * + * @throws APIException + */ + public function extractStream( + string $id, + array|SessionExtractParams $params, + ?RequestOptions $requestOptions = null, + ): BaseResponse; + /** * @api * @@ -120,6 +170,22 @@ public function observe( ?RequestOptions $requestOptions = null, ): BaseResponse; + /** + * @api + * + * @param string $id Path param: Unique session identifier + * @param array|SessionObserveParams $params + * + * @return BaseResponse> + * + * @throws APIException + */ + public function observeStream( + string $id, + array|SessionObserveParams $params, + ?RequestOptions $requestOptions = null, + ): BaseResponse; + /** * @api * diff --git a/src/Services/SessionsRawService.php b/src/Services/SessionsRawService.php index 484541d..c84b4f2 100644 --- a/src/Services/SessionsRawService.php +++ b/src/Services/SessionsRawService.php @@ -6,15 +6,17 @@ use Stagehand\Client; use Stagehand\Core\Contracts\BaseResponse; +use Stagehand\Core\Contracts\BaseStream; use Stagehand\Core\Exceptions\APIException; use Stagehand\Core\Util; use Stagehand\RequestOptions; use Stagehand\ServiceContracts\SessionsRawContract; +use Stagehand\Sessions\Action; use Stagehand\Sessions\SessionActParams; -use Stagehand\Sessions\SessionActParams\XLanguage; -use Stagehand\Sessions\SessionActParams\XStreamResponse; use Stagehand\Sessions\SessionActResponse; use Stagehand\Sessions\SessionEndParams; +use Stagehand\Sessions\SessionEndParams\XLanguage; +use Stagehand\Sessions\SessionEndParams\XStreamResponse; use Stagehand\Sessions\SessionEndResponse; use Stagehand\Sessions\SessionExecuteParams; use Stagehand\Sessions\SessionExecuteResponse; @@ -30,6 +32,8 @@ use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\HTTPVersion; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Region; use Stagehand\Sessions\SessionStartResponse; +use Stagehand\Sessions\StreamEvent; +use Stagehand\SSEStream; final class SessionsRawService implements SessionsRawContract { @@ -51,17 +55,17 @@ public function __construct(private Client $client) {} * selector: string, * arguments?: list, * method?: string, - * }, + * }|Action, * frameID?: string, * options?: array{ * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, * timeout?: float, * variables?: array, * }, - * xLanguage?: 'typescript'|'python'|'playground'|XLanguage, + * xLanguage?: 'typescript'|'python'|'playground'|SessionActParams\XLanguage, * xSDKVersion?: string, * xSentAt?: string|\DateTimeInterface, - * xStreamResponse?: 'true'|'false'|XStreamResponse, + * xStreamResponse?: 'true'|'false'|SessionActParams\XStreamResponse, * }|SessionActParams $params * * @return BaseResponse @@ -101,6 +105,74 @@ public function act( ); } + /** + * @api + * + * @param string $id Path param: Unique session identifier + * @param array{ + * input: string|array{ + * description: string, + * selector: string, + * arguments?: list, + * method?: string, + * }|Action, + * frameID?: string, + * options?: array{ + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * timeout?: float, + * variables?: array, + * }, + * xLanguage?: 'typescript'|'python'|'playground'|SessionActParams\XLanguage, + * xSDKVersion?: string, + * xSentAt?: string|\DateTimeInterface, + * xStreamResponse?: 'true'|'false'|SessionActParams\XStreamResponse, + * }|SessionActParams $params + * + * @return BaseResponse> + * + * @throws APIException + */ + public function actStream( + string $id, + array|SessionActParams $params, + ?RequestOptions $requestOptions = null, + ): BaseResponse { + [$parsed, $options] = SessionActParams::parseRequest( + $params, + $requestOptions, + ); + $parsed['streamResponse'] = true; + $header_params = [ + 'xLanguage' => 'x-language', + 'xSDKVersion' => 'x-sdk-version', + 'xSentAt' => 'x-sent-at', + 'xStreamResponse' => 'x-stream-response', + ]; + + // @phpstan-ignore-next-line return.type + return $this->client->request( + method: 'post', + path: ['v1/sessions/%1$s/act', $id], + headers: Util::array_transform_keys( + [ + 'Accept' => 'text/event-stream', + ...array_intersect_key( + $parsed, + array_flip(array_keys($header_params)) + ), + ], + $header_params, + ), + body: (object) array_diff_key( + $parsed, + array_flip(array_keys($header_params)) + ), + options: $options, + convert: StreamEvent::class, + stream: SSEStream::class, + ); + } + /** * @api * @@ -108,10 +180,10 @@ public function act( * * @param string $id Unique session identifier * @param array{ - * xLanguage?: 'typescript'|'python'|'playground'|SessionEndParams\XLanguage, + * xLanguage?: 'typescript'|'python'|'playground'|XLanguage, * xSDKVersion?: string, * xSentAt?: string|\DateTimeInterface, - * xStreamResponse?: 'true'|'false'|SessionEndParams\XStreamResponse, + * xStreamResponse?: 'true'|'false'|XStreamResponse, * }|SessionEndParams $params * * @return BaseResponse @@ -205,6 +277,71 @@ public function execute( ); } + /** + * @api + * + * @param string $id Path param: Unique session identifier + * @param array{ + * agentConfig: array{ + * cua?: bool, + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * systemPrompt?: string, + * }, + * executeOptions: array{ + * instruction: string, highlightCursor?: bool, maxSteps?: float + * }, + * frameID?: string, + * xLanguage?: 'typescript'|'python'|'playground'|SessionExecuteParams\XLanguage, + * xSDKVersion?: string, + * xSentAt?: string|\DateTimeInterface, + * xStreamResponse?: 'true'|'false'|SessionExecuteParams\XStreamResponse, + * }|SessionExecuteParams $params + * + * @return BaseResponse> + * + * @throws APIException + */ + public function executeStream( + string $id, + array|SessionExecuteParams $params, + ?RequestOptions $requestOptions = null, + ): BaseResponse { + [$parsed, $options] = SessionExecuteParams::parseRequest( + $params, + $requestOptions, + ); + $parsed['streamResponse'] = true; + $header_params = [ + 'xLanguage' => 'x-language', + 'xSDKVersion' => 'x-sdk-version', + 'xSentAt' => 'x-sent-at', + 'xStreamResponse' => 'x-stream-response', + ]; + + // @phpstan-ignore-next-line return.type + return $this->client->request( + method: 'post', + path: ['v1/sessions/%1$s/agentExecute', $id], + headers: Util::array_transform_keys( + [ + 'Accept' => 'text/event-stream', + ...array_intersect_key( + $parsed, + array_flip(array_keys($header_params)) + ), + ], + $header_params, + ), + body: (object) array_diff_key( + $parsed, + array_flip(array_keys($header_params)) + ), + options: $options, + convert: StreamEvent::class, + stream: SSEStream::class, + ); + } + /** * @api * @@ -263,6 +400,70 @@ public function extract( ); } + /** + * @api + * + * @param string $id Path param: Unique session identifier + * @param array{ + * frameID?: string, + * instruction?: string, + * options?: array{ + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * selector?: string, + * timeout?: float, + * }, + * schema?: array, + * xLanguage?: 'typescript'|'python'|'playground'|SessionExtractParams\XLanguage, + * xSDKVersion?: string, + * xSentAt?: string|\DateTimeInterface, + * xStreamResponse?: 'true'|'false'|SessionExtractParams\XStreamResponse, + * }|SessionExtractParams $params + * + * @return BaseResponse> + * + * @throws APIException + */ + public function extractStream( + string $id, + array|SessionExtractParams $params, + ?RequestOptions $requestOptions = null, + ): BaseResponse { + [$parsed, $options] = SessionExtractParams::parseRequest( + $params, + $requestOptions, + ); + $parsed['streamResponse'] = true; + $header_params = [ + 'xLanguage' => 'x-language', + 'xSDKVersion' => 'x-sdk-version', + 'xSentAt' => 'x-sent-at', + 'xStreamResponse' => 'x-stream-response', + ]; + + // @phpstan-ignore-next-line return.type + return $this->client->request( + method: 'post', + path: ['v1/sessions/%1$s/extract', $id], + headers: Util::array_transform_keys( + [ + 'Accept' => 'text/event-stream', + ...array_intersect_key( + $parsed, + array_flip(array_keys($header_params)) + ), + ], + $header_params, + ), + body: (object) array_diff_key( + $parsed, + array_flip(array_keys($header_params)) + ), + options: $options, + convert: StreamEvent::class, + stream: SSEStream::class, + ); + } + /** * @api * @@ -277,6 +478,7 @@ public function extract( * timeout?: float, * waitUntil?: 'load'|'domcontentloaded'|'networkidle'|WaitUntil, * }, + * streamResponse?: bool, * xLanguage?: 'typescript'|'python'|'playground'|SessionNavigateParams\XLanguage, * xSDKVersion?: string, * xSentAt?: string|\DateTimeInterface, @@ -377,6 +579,69 @@ public function observe( ); } + /** + * @api + * + * @param string $id Path param: Unique session identifier + * @param array{ + * frameID?: string, + * instruction?: string, + * options?: array{ + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * selector?: string, + * timeout?: float, + * }, + * xLanguage?: 'typescript'|'python'|'playground'|SessionObserveParams\XLanguage, + * xSDKVersion?: string, + * xSentAt?: string|\DateTimeInterface, + * xStreamResponse?: 'true'|'false'|SessionObserveParams\XStreamResponse, + * }|SessionObserveParams $params + * + * @return BaseResponse> + * + * @throws APIException + */ + public function observeStream( + string $id, + array|SessionObserveParams $params, + ?RequestOptions $requestOptions = null, + ): BaseResponse { + [$parsed, $options] = SessionObserveParams::parseRequest( + $params, + $requestOptions, + ); + $parsed['streamResponse'] = true; + $header_params = [ + 'xLanguage' => 'x-language', + 'xSDKVersion' => 'x-sdk-version', + 'xSentAt' => 'x-sent-at', + 'xStreamResponse' => 'x-stream-response', + ]; + + // @phpstan-ignore-next-line return.type + return $this->client->request( + method: 'post', + path: ['v1/sessions/%1$s/observe', $id], + headers: Util::array_transform_keys( + [ + 'Accept' => 'text/event-stream', + ...array_intersect_key( + $parsed, + array_flip(array_keys($header_params)) + ), + ], + $header_params, + ), + body: (object) array_diff_key( + $parsed, + array_flip(array_keys($header_params)) + ), + options: $options, + convert: StreamEvent::class, + stream: SSEStream::class, + ); + } + /** * @api * diff --git a/src/Services/SessionsService.php b/src/Services/SessionsService.php index 05a4fcc..49c486d 100644 --- a/src/Services/SessionsService.php +++ b/src/Services/SessionsService.php @@ -5,10 +5,12 @@ namespace Stagehand\Services; use Stagehand\Client; +use Stagehand\Core\Contracts\BaseStream; use Stagehand\Core\Exceptions\APIException; use Stagehand\Core\Util; use Stagehand\RequestOptions; use Stagehand\ServiceContracts\SessionsContract; +use Stagehand\Sessions\Action; use Stagehand\Sessions\SessionActParams\XLanguage; use Stagehand\Sessions\SessionActParams\XStreamResponse; use Stagehand\Sessions\SessionActResponse; @@ -25,6 +27,7 @@ use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\OperatingSystem; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Region; use Stagehand\Sessions\SessionStartResponse; +use Stagehand\Sessions\StreamEvent; final class SessionsService implements SessionsContract { @@ -52,7 +55,7 @@ public function __construct(private Client $client) * selector: string, * arguments?: list, * method?: string, - * } $input Body param: Natural language instruction or Action object + * }|Action $input Body param: Natural language instruction or Action object * @param string $frameID Body param: Target frame ID for the action * @param array{ * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, @@ -68,7 +71,7 @@ public function __construct(private Client $client) */ public function act( string $id, - string|array $input, + string|array|Action $input, ?string $frameID = null, ?array $options = null, string|XLanguage|null $xLanguage = null, @@ -95,6 +98,60 @@ public function act( return $response->parse(); } + /** + * @api + * + * @param string $id Path param: Unique session identifier + * @param string|array{ + * description: string, + * selector: string, + * arguments?: list, + * method?: string, + * }|Action $input Body param: Natural language instruction or Action object + * @param string $frameID Body param: Target frame ID for the action + * @param array{ + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * timeout?: float, + * variables?: array, + * } $options Body param: + * @param 'typescript'|'python'|'playground'|XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE + * + * @return BaseStream + * + * @throws APIException + */ + public function actStream( + string $id, + string|array|Action $input, + ?string $frameID = null, + ?array $options = null, + string|XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|XStreamResponse|null $xStreamResponse = null, + ?RequestOptions $requestOptions = null, + ): BaseStream { + $params = Util::removeNulls( + [ + 'input' => $input, + 'frameID' => $frameID, + 'options' => $options, + 'xLanguage' => $xLanguage, + 'xSDKVersion' => $xSDKVersion, + 'xSentAt' => $xSentAt, + 'xStreamResponse' => $xStreamResponse, + ], + ); + + // @phpstan-ignore-next-line argument.type + $response = $this->raw->actStream($id, params: $params, requestOptions: $requestOptions); + + return $response->parse(); + } + /** * @api * @@ -182,6 +239,57 @@ public function execute( return $response->parse(); } + /** + * @api + * + * @param string $id Path param: Unique session identifier + * @param array{ + * cua?: bool, + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * systemPrompt?: string, + * } $agentConfig Body param: + * @param array{ + * instruction: string, highlightCursor?: bool, maxSteps?: float + * } $executeOptions Body param: + * @param string $frameID Body param: Target frame ID for the agent + * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionExecuteParams\XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|\Stagehand\Sessions\SessionExecuteParams\XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE + * + * @return BaseStream + * + * @throws APIException + */ + public function executeStream( + string $id, + array $agentConfig, + array $executeOptions, + ?string $frameID = null, + string|\Stagehand\Sessions\SessionExecuteParams\XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|\Stagehand\Sessions\SessionExecuteParams\XStreamResponse|null $xStreamResponse = null, + ?RequestOptions $requestOptions = null, + ): BaseStream { + $params = Util::removeNulls( + [ + 'agentConfig' => $agentConfig, + 'executeOptions' => $executeOptions, + 'frameID' => $frameID, + 'xLanguage' => $xLanguage, + 'xSDKVersion' => $xSDKVersion, + 'xSentAt' => $xSentAt, + 'xStreamResponse' => $xStreamResponse, + ], + ); + + // @phpstan-ignore-next-line argument.type + $response = $this->raw->executeStream($id, params: $params, requestOptions: $requestOptions); + + return $response->parse(); + } + /** * @api * @@ -234,6 +342,58 @@ public function extract( return $response->parse(); } + /** + * @api + * + * @param string $id Path param: Unique session identifier + * @param string $frameID Body param: Target frame ID for the extraction + * @param string $instruction Body param: Natural language instruction for what to extract + * @param array{ + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * selector?: string, + * timeout?: float, + * } $options Body param: + * @param array $schema Body param: JSON Schema defining the structure of data to extract + * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionExtractParams\XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|\Stagehand\Sessions\SessionExtractParams\XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE + * + * @return BaseStream + * + * @throws APIException + */ + public function extractStream( + string $id, + ?string $frameID = null, + ?string $instruction = null, + ?array $options = null, + ?array $schema = null, + string|\Stagehand\Sessions\SessionExtractParams\XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|\Stagehand\Sessions\SessionExtractParams\XStreamResponse|null $xStreamResponse = null, + ?RequestOptions $requestOptions = null, + ): BaseStream { + $params = Util::removeNulls( + [ + 'frameID' => $frameID, + 'instruction' => $instruction, + 'options' => $options, + 'schema' => $schema, + 'xLanguage' => $xLanguage, + 'xSDKVersion' => $xSDKVersion, + 'xSentAt' => $xSentAt, + 'xStreamResponse' => $xStreamResponse, + ], + ); + + // @phpstan-ignore-next-line argument.type + $response = $this->raw->extractStream($id, params: $params, requestOptions: $requestOptions); + + return $response->parse(); + } + /** * @api * @@ -247,6 +407,7 @@ public function extract( * timeout?: float, * waitUntil?: 'load'|'domcontentloaded'|'networkidle'|WaitUntil, * } $options Body param: + * @param bool $streamResponse Body param: Whether to stream the response via SSE * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionNavigateParams\XLanguage $xLanguage Header param: Client SDK language * @param string $xSDKVersion Header param: Version of the Stagehand SDK * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent @@ -259,6 +420,7 @@ public function navigate( string $url, ?string $frameID = null, ?array $options = null, + ?bool $streamResponse = null, string|\Stagehand\Sessions\SessionNavigateParams\XLanguage|null $xLanguage = null, ?string $xSDKVersion = null, string|\DateTimeInterface|null $xSentAt = null, @@ -270,6 +432,7 @@ public function navigate( 'url' => $url, 'frameID' => $frameID, 'options' => $options, + 'streamResponse' => $streamResponse, 'xLanguage' => $xLanguage, 'xSDKVersion' => $xSDKVersion, 'xSentAt' => $xSentAt, @@ -332,6 +495,55 @@ public function observe( return $response->parse(); } + /** + * @api + * + * @param string $id Path param: Unique session identifier + * @param string $frameID Body param: Target frame ID for the observation + * @param string $instruction Body param: Natural language instruction for what actions to find + * @param array{ + * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * selector?: string, + * timeout?: float, + * } $options Body param: + * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionObserveParams\XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|\Stagehand\Sessions\SessionObserveParams\XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE + * + * @return BaseStream + * + * @throws APIException + */ + public function observeStream( + string $id, + ?string $frameID = null, + ?string $instruction = null, + ?array $options = null, + string|\Stagehand\Sessions\SessionObserveParams\XLanguage|null $xLanguage = null, + ?string $xSDKVersion = null, + string|\DateTimeInterface|null $xSentAt = null, + string|\Stagehand\Sessions\SessionObserveParams\XStreamResponse|null $xStreamResponse = null, + ?RequestOptions $requestOptions = null, + ): BaseStream { + $params = Util::removeNulls( + [ + 'frameID' => $frameID, + 'instruction' => $instruction, + 'options' => $options, + 'xLanguage' => $xLanguage, + 'xSDKVersion' => $xSDKVersion, + 'xSentAt' => $xSentAt, + 'xStreamResponse' => $xStreamResponse, + ], + ); + + // @phpstan-ignore-next-line argument.type + $response = $this->raw->observeStream($id, params: $params, requestOptions: $requestOptions); + + return $response->parse(); + } + /** * @api * diff --git a/src/Sessions/SessionActParams.php b/src/Sessions/SessionActParams.php index 979430b..4be2342 100644 --- a/src/Sessions/SessionActParams.php +++ b/src/Sessions/SessionActParams.php @@ -9,7 +9,6 @@ use Stagehand\Core\Concerns\SdkModel; use Stagehand\Core\Concerns\SdkParams; use Stagehand\Core\Contracts\BaseModel; -use Stagehand\Sessions\SessionActParams\Input\ActionInput; use Stagehand\Sessions\SessionActParams\Options; use Stagehand\Sessions\SessionActParams\XLanguage; use Stagehand\Sessions\SessionActParams\XStreamResponse; @@ -42,7 +41,7 @@ final class SessionActParams implements BaseModel * Natural language instruction or Action object. */ #[Required] - public string|ActionInput $input; + public string|Action $input; /** * Target frame ID for the action. @@ -111,7 +110,7 @@ public function __construct() * @param XStreamResponse|value-of $xStreamResponse */ public static function with( - string|ActionInput|array $input, + string|Action|array $input, ?string $frameID = null, Options|array|null $options = null, XLanguage|string|null $xLanguage = null, @@ -138,7 +137,7 @@ public static function with( * * @param InputShape $input */ - public function withInput(string|ActionInput|array $input): self + public function withInput(string|Action|array $input): self { $self = clone $this; $self['input'] = $input; diff --git a/src/Sessions/SessionActParams/Input.php b/src/Sessions/SessionActParams/Input.php index 8a338a4..8e6a27e 100644 --- a/src/Sessions/SessionActParams/Input.php +++ b/src/Sessions/SessionActParams/Input.php @@ -7,14 +7,14 @@ use Stagehand\Core\Concerns\SdkUnion; use Stagehand\Core\Conversion\Contracts\Converter; use Stagehand\Core\Conversion\Contracts\ConverterSource; -use Stagehand\Sessions\SessionActParams\Input\ActionInput; +use Stagehand\Sessions\Action; /** * Natural language instruction or Action object. * - * @phpstan-import-type ActionInputShape from \Stagehand\Sessions\SessionActParams\Input\ActionInput + * @phpstan-import-type ActionShape from \Stagehand\Sessions\Action * - * @phpstan-type InputShape = string|ActionInputShape + * @phpstan-type InputShape = string|ActionShape */ final class Input implements ConverterSource { @@ -25,6 +25,6 @@ final class Input implements ConverterSource */ public static function variants(): array { - return ['string', ActionInput::class]; + return ['string', Action::class]; } } diff --git a/src/Sessions/SessionActParams/Input/ActionInput.php b/src/Sessions/SessionActParams/Input/ActionInput.php deleted file mode 100644 index e5a16c0..0000000 --- a/src/Sessions/SessionActParams/Input/ActionInput.php +++ /dev/null @@ -1,141 +0,0 @@ -|null, - * method?: string|null, - * } - */ -final class ActionInput implements BaseModel -{ - /** @use SdkModel */ - use SdkModel; - - /** - * Human-readable description of the action. - */ - #[Required] - public string $description; - - /** - * CSS selector or XPath for the element. - */ - #[Required] - public string $selector; - - /** - * Arguments to pass to the method. - * - * @var list|null $arguments - */ - #[Optional(list: 'string')] - public ?array $arguments; - - /** - * The method to execute (click, fill, etc.). - */ - #[Optional] - public ?string $method; - - /** - * `new ActionInput()` is missing required properties by the API. - * - * To enforce required parameters use - * ``` - * ActionInput::with(description: ..., selector: ...) - * ``` - * - * Otherwise ensure the following setters are called - * - * ``` - * (new ActionInput)->withDescription(...)->withSelector(...) - * ``` - */ - public function __construct() - { - $this->initialize(); - } - - /** - * Construct an instance from the required parameters. - * - * You must use named parameters to construct any parameters with a default value. - * - * @param list $arguments - */ - public static function with( - string $description, - string $selector, - ?array $arguments = null, - ?string $method = null, - ): self { - $self = new self; - - $self['description'] = $description; - $self['selector'] = $selector; - - null !== $arguments && $self['arguments'] = $arguments; - null !== $method && $self['method'] = $method; - - return $self; - } - - /** - * Human-readable description of the action. - */ - public function withDescription(string $description): self - { - $self = clone $this; - $self['description'] = $description; - - return $self; - } - - /** - * CSS selector or XPath for the element. - */ - public function withSelector(string $selector): self - { - $self = clone $this; - $self['selector'] = $selector; - - return $self; - } - - /** - * Arguments to pass to the method. - * - * @param list $arguments - */ - public function withArguments(array $arguments): self - { - $self = clone $this; - $self['arguments'] = $arguments; - - return $self; - } - - /** - * The method to execute (click, fill, etc.). - */ - public function withMethod(string $method): self - { - $self = clone $this; - $self['method'] = $method; - - return $self; - } -} diff --git a/src/Sessions/SessionNavigateParams.php b/src/Sessions/SessionNavigateParams.php index ccfdbe5..d4a359a 100644 --- a/src/Sessions/SessionNavigateParams.php +++ b/src/Sessions/SessionNavigateParams.php @@ -24,6 +24,7 @@ * url: string, * frameID?: string|null, * options?: OptionsShape|null, + * streamResponse?: bool|null, * xLanguage?: null|XLanguage|value-of, * xSDKVersion?: string|null, * xSentAt?: \DateTimeInterface|null, @@ -51,6 +52,12 @@ final class SessionNavigateParams implements BaseModel #[Optional] public ?Options $options; + /** + * Whether to stream the response via SSE. + */ + #[Optional] + public ?bool $streamResponse; + /** * Client SDK language. * @@ -111,6 +118,7 @@ public static function with( string $url, ?string $frameID = null, Options|array|null $options = null, + ?bool $streamResponse = null, XLanguage|string|null $xLanguage = null, ?string $xSDKVersion = null, ?\DateTimeInterface $xSentAt = null, @@ -122,6 +130,7 @@ public static function with( null !== $frameID && $self['frameID'] = $frameID; null !== $options && $self['options'] = $options; + null !== $streamResponse && $self['streamResponse'] = $streamResponse; null !== $xLanguage && $self['xLanguage'] = $xLanguage; null !== $xSDKVersion && $self['xSDKVersion'] = $xSDKVersion; null !== $xSentAt && $self['xSentAt'] = $xSentAt; @@ -163,6 +172,17 @@ public function withOptions(Options|array $options): self return $self; } + /** + * Whether to stream the response via SSE. + */ + public function withStreamResponse(bool $streamResponse): self + { + $self = clone $this; + $self['streamResponse'] = $streamResponse; + + return $self; + } + /** * Client SDK language. * diff --git a/src/Sessions/SessionStartResponse/Data.php b/src/Sessions/SessionStartResponse/Data.php index 461235a..9dd36e3 100644 --- a/src/Sessions/SessionStartResponse/Data.php +++ b/src/Sessions/SessionStartResponse/Data.php @@ -9,7 +9,9 @@ use Stagehand\Core\Contracts\BaseModel; /** - * @phpstan-type DataShape = array{available: bool, sessionID: string} + * @phpstan-type DataShape = array{ + * available: bool, connectURL: string, sessionID: string + * } */ final class Data implements BaseModel { @@ -20,7 +22,13 @@ final class Data implements BaseModel public bool $available; /** - * Unique session identifier. + * CDP WebSocket URL for connecting to the Browserbase cloud browser. + */ + #[Required('connectUrl')] + public string $connectURL; + + /** + * Unique Browserbase session identifier. */ #[Required('sessionId')] public string $sessionID; @@ -30,13 +38,13 @@ final class Data implements BaseModel * * To enforce required parameters use * ``` - * Data::with(available: ..., sessionID: ...) + * Data::with(available: ..., connectURL: ..., sessionID: ...) * ``` * * Otherwise ensure the following setters are called * * ``` - * (new Data)->withAvailable(...)->withSessionID(...) + * (new Data)->withAvailable(...)->withConnectURL(...)->withSessionID(...) * ``` */ public function __construct() @@ -49,11 +57,15 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. */ - public static function with(bool $available, string $sessionID): self - { + public static function with( + bool $available, + string $connectURL, + string $sessionID + ): self { $self = new self; $self['available'] = $available; + $self['connectURL'] = $connectURL; $self['sessionID'] = $sessionID; return $self; @@ -68,7 +80,18 @@ public function withAvailable(bool $available): self } /** - * Unique session identifier. + * CDP WebSocket URL for connecting to the Browserbase cloud browser. + */ + public function withConnectURL(string $connectURL): self + { + $self = clone $this; + $self['connectURL'] = $connectURL; + + return $self; + } + + /** + * Unique Browserbase session identifier. */ public function withSessionID(string $sessionID): self { diff --git a/src/Sessions/StreamEvent.php b/src/Sessions/StreamEvent.php new file mode 100644 index 0000000..ba75c87 --- /dev/null +++ b/src/Sessions/StreamEvent.php @@ -0,0 +1,123 @@ +\n\n`. + * + * @phpstan-import-type DataShape from \Stagehand\Sessions\StreamEvent\Data + * + * @phpstan-type StreamEventShape = array{ + * id: string, + * data: StreamEventSystemDataOutput|StreamEventLogDataOutput|DataShape, + * type: Type|value-of, + * } + */ +final class StreamEvent implements BaseModel +{ + /** @use SdkModel */ + use SdkModel; + + /** + * Unique identifier for this event. + */ + #[Required] + public string $id; + + #[Required] + public StreamEventSystemDataOutput|StreamEventLogDataOutput $data; + + /** + * Type of stream event - system events or log messages. + * + * @var value-of $type + */ + #[Required(enum: Type::class)] + public string $type; + + /** + * `new StreamEvent()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * StreamEvent::with(id: ..., data: ..., type: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new StreamEvent)->withID(...)->withData(...)->withType(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param DataShape $data + * @param Type|value-of $type + */ + public static function with( + string $id, + StreamEventSystemDataOutput|array|StreamEventLogDataOutput $data, + Type|string $type, + ): self { + $self = new self; + + $self['id'] = $id; + $self['data'] = $data; + $self['type'] = $type; + + return $self; + } + + /** + * Unique identifier for this event. + */ + public function withID(string $id): self + { + $self = clone $this; + $self['id'] = $id; + + return $self; + } + + /** + * @param DataShape $data + */ + public function withData( + StreamEventSystemDataOutput|array|StreamEventLogDataOutput $data + ): self { + $self = clone $this; + $self['data'] = $data; + + return $self; + } + + /** + * Type of stream event - system events or log messages. + * + * @param Type|value-of $type + */ + public function withType(Type|string $type): self + { + $self = clone $this; + $self['type'] = $type; + + return $self; + } +} diff --git a/src/Sessions/StreamEvent/Data.php b/src/Sessions/StreamEvent/Data.php new file mode 100644 index 0000000..7f95224 --- /dev/null +++ b/src/Sessions/StreamEvent/Data.php @@ -0,0 +1,32 @@ +|array + */ + public static function variants(): array + { + return [ + StreamEventSystemDataOutput::class, StreamEventLogDataOutput::class, + ]; + } +} diff --git a/src/Sessions/StreamEvent/Data/StreamEventLogDataOutput.php b/src/Sessions/StreamEvent/Data/StreamEventLogDataOutput.php new file mode 100644 index 0000000..5477691 --- /dev/null +++ b/src/Sessions/StreamEvent/Data/StreamEventLogDataOutput.php @@ -0,0 +1,74 @@ + */ + use SdkModel; + + /** @var 'running' $status */ + #[Required] + public string $status = 'running'; + + /** + * Log message from the operation. + */ + #[Required] + public string $message; + + /** + * `new StreamEventLogDataOutput()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * StreamEventLogDataOutput::with(message: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new StreamEventLogDataOutput)->withMessage(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + */ + public static function with(string $message): self + { + $self = new self; + + $self['message'] = $message; + + return $self; + } + + /** + * Log message from the operation. + */ + public function withMessage(string $message): self + { + $self = clone $this; + $self['message'] = $message; + + return $self; + } +} diff --git a/src/Sessions/StreamEvent/Data/StreamEventSystemDataOutput.php b/src/Sessions/StreamEvent/Data/StreamEventSystemDataOutput.php new file mode 100644 index 0000000..1d6cbef --- /dev/null +++ b/src/Sessions/StreamEvent/Data/StreamEventSystemDataOutput.php @@ -0,0 +1,118 @@ +, error?: string|null, result?: mixed + * } + */ +final class StreamEventSystemDataOutput implements BaseModel +{ + /** @use SdkModel */ + use SdkModel; + + /** + * Current status of the streaming operation. + * + * @var value-of $status + */ + #[Required(enum: Status::class)] + public string $status; + + /** + * Error message (present when status is 'error'). + */ + #[Optional] + public ?string $error; + + /** + * Operation result (present when status is 'finished'). + */ + #[Optional] + public mixed $result; + + /** + * `new StreamEventSystemDataOutput()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * StreamEventSystemDataOutput::with(status: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new StreamEventSystemDataOutput)->withStatus(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param Status|value-of $status + */ + public static function with( + Status|string $status, + ?string $error = null, + mixed $result = null + ): self { + $self = new self; + + $self['status'] = $status; + + null !== $error && $self['error'] = $error; + null !== $result && $self['result'] = $result; + + return $self; + } + + /** + * Current status of the streaming operation. + * + * @param Status|value-of $status + */ + public function withStatus(Status|string $status): self + { + $self = clone $this; + $self['status'] = $status; + + return $self; + } + + /** + * Error message (present when status is 'error'). + */ + public function withError(string $error): self + { + $self = clone $this; + $self['error'] = $error; + + return $self; + } + + /** + * Operation result (present when status is 'finished'). + */ + public function withResult(mixed $result): self + { + $self = clone $this; + $self['result'] = $result; + + return $self; + } +} diff --git a/src/Sessions/StreamEvent/Data/StreamEventSystemDataOutput/Status.php b/src/Sessions/StreamEvent/Data/StreamEventSystemDataOutput/Status.php new file mode 100644 index 0000000..4c30706 --- /dev/null +++ b/src/Sessions/StreamEvent/Data/StreamEventSystemDataOutput/Status.php @@ -0,0 +1,21 @@ + 'referer', 'timeout' => 30000, 'waitUntil' => 'networkidle', ], + streamResponse: true, xLanguage: 'typescript', xSDKVersion: '3.0.6', xSentAt: new \DateTimeImmutable('2025-01-15T10:30:00Z'), From 8935e42bd30fb4d0a81a211b11c098181404e360 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 05:59:04 +0000 Subject: [PATCH 15/29] chore(internal): codegen related update --- src/Core/Attributes/Api.php | 66 +++++++ src/Core/Concerns/SdkResponse.php | 29 +++ .../Contracts/ResponseConverter.php | 18 ++ tests/Core/TestModel.php | 181 ++++++++++++++++++ 4 files changed, 294 insertions(+) create mode 100644 src/Core/Attributes/Api.php create mode 100644 src/Core/Concerns/SdkResponse.php create mode 100644 src/Core/Conversion/Contracts/ResponseConverter.php create mode 100644 tests/Core/TestModel.php diff --git a/src/Core/Attributes/Api.php b/src/Core/Attributes/Api.php new file mode 100644 index 0000000..192fd09 --- /dev/null +++ b/src/Core/Attributes/Api.php @@ -0,0 +1,66 @@ +|Converter|string|null */ + public readonly Converter|string|null $type; + + /** @var array */ + private static array $enumConverters = []; + + /** + * @param class-string|Converter|string|null $type + * @param class-string<\BackedEnum>|Converter|null $enum + * @param class-string|Converter|null $union + * @param class-string|Converter|string|null $list + * @param class-string|Converter|string|null $map + */ + public function __construct( + public readonly ?string $apiName = null, + Converter|string|null $type = null, + Converter|string|null $enum = null, + Converter|string|null $union = null, + Converter|string|null $list = null, + Converter|string|null $map = null, + public readonly bool $nullable = false, + public readonly bool $optional = false, + ) { + $type ??= $union; + if (null !== $list) { + $type ??= new ListOf($list); + } + if (null !== $map) { + $type ??= new MapOf($map); + } + if (null !== $enum) { + $type ??= $enum instanceof Converter ? $enum : $this->getEnumConverter($enum); + } + + $this->type = $type; + } + + /** @property class-string<\BackedEnum> $enum */ + private function getEnumConverter(string $enum): Converter + { + if (!isset(self::$enumConverters[$enum])) { + $converter = new EnumOf(array_column($enum::cases(), 'value')); // @phpstan-ignore-line + self::$enumConverters[$enum] = $converter; + } + + return self::$enumConverters[$enum]; + } +} diff --git a/src/Core/Concerns/SdkResponse.php b/src/Core/Concerns/SdkResponse.php new file mode 100644 index 0000000..26fb402 --- /dev/null +++ b/src/Core/Concerns/SdkResponse.php @@ -0,0 +1,29 @@ +_rawResponse = $response; + $instance->__unserialize(Util::decodeContent($response)); // @phpstan-ignore-line + + return $instance; + } + + public function getRawResponse(): ?ResponseInterface + { + return $this->_rawResponse; + } +} diff --git a/src/Core/Conversion/Contracts/ResponseConverter.php b/src/Core/Conversion/Contracts/ResponseConverter.php new file mode 100644 index 0000000..1331c18 --- /dev/null +++ b/src/Core/Conversion/Contracts/ResponseConverter.php @@ -0,0 +1,18 @@ +> */ + use SdkModel; + + #[Required] + public string $name; + + #[Required('age_years')] + public int $ageYears; + + /** @var list|null */ + #[Optional] + public ?array $friends; + + #[Required] + public ?string $owner; + + /** + * @param list|null $friends + */ + public function __construct( + string $name, + int $ageYears, + ?string $owner, + ?array $friends = null, + ) { + $this->initialize(); + + $this->name = $name; + $this->ageYears = $ageYears; + $this->owner = $owner; + + null != $friends && $this->friends = $friends; + } +} + +/** + * @internal + * + * @coversNothing + */ +#[CoversNothing] +class TestModelTest extends TestCase +{ + #[Test] + public function testBasicGetAndSet(): void + { + $model = new TestModel( + name: 'Bob', + ageYears: 12, + owner: null, + ); + $this->assertEquals(12, $model->ageYears); + + ++$model->ageYears; + $this->assertEquals(13, $model->ageYears); + } + + #[Test] + public function testNullAccess(): void + { + $model = new TestModel( + name: 'Bob', + ageYears: 12, + owner: null, + ); + $this->assertNull($model->owner); + $this->assertNull($model->friends); + } + + #[Test] + public function testArrayGetAndSet(): void + { + $model = new TestModel( + name: 'Bob', + ageYears: 12, + owner: null, + ); + $model->friends ??= []; + $this->assertEquals([], $model->friends); + $model->friends[] = 'Alice'; + $this->assertEquals(['Alice'], $model->friends); + } + + #[Test] + public function testDiscernsBetweenNullAndUnset(): void + { + $modelUnsetFriends = new TestModel( + name: 'Bob', + ageYears: 12, + owner: null, + ); + $modelNullFriends = new TestModel( + name: 'bob', + ageYears: 12, + owner: null, + ); + $modelNullFriends->friends = null; + + $this->assertEquals(12, $modelUnsetFriends->ageYears); + $this->assertEquals(12, $modelNullFriends->ageYears); + + $this->assertTrue($modelUnsetFriends->offsetExists('ageYears')); + $this->assertTrue($modelNullFriends->offsetExists('ageYears')); + + $this->assertNull($modelUnsetFriends->friends); + $this->assertNull($modelNullFriends->friends); + + $this->assertFalse($modelUnsetFriends->offsetExists('friends')); + $this->assertTrue($modelNullFriends->offsetExists('friends')); + } + + #[Test] + public function testIssetOnOmittedProperties(): void + { + $model = new TestModel( + name: 'Bob', + ageYears: 12, + owner: null, + ); + $this->assertFalse(isset($model->owner)); + $this->assertFalse(isset($model->friends)); + } + + #[Test] + public function testSerializeBasicModel(): void + { + $model = new TestModel( + name: 'Bob', + ageYears: 12, + owner: 'Eve', + friends: ['Alice', 'Charlie'], + ); + $this->assertEquals( + '{"name":"Bob","age_years":12,"friends":["Alice","Charlie"],"owner":"Eve"}', + json_encode($model) + ); + } + + #[Test] + public function testSerializeModelWithOmittedProperties(): void + { + $model = new TestModel( + name: 'Bob', + ageYears: 12, + owner: null, + ); + $this->assertEquals( + '{"name":"Bob","age_years":12,"owner":null}', + json_encode($model) + ); + } + + #[Test] + public function testSerializeModelWithExplicitNull(): void + { + $model = new TestModel( + name: 'Bob', + ageYears: 12, + owner: null, + ); + $model->friends = null; + $this->assertEquals( + '{"name":"Bob","age_years":12,"friends":null,"owner":null}', + json_encode($model) + ); + } +} From 3ce08d172eba2c771edcd7d7cd81fdc461547c8b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 06:00:04 +0000 Subject: [PATCH 16/29] chore(internal): codegen related update --- src/Core/Attributes/Api.php | 66 ------- src/Core/Concerns/SdkResponse.php | 29 --- .../Contracts/ResponseConverter.php | 18 -- tests/Core/TestModel.php | 181 ------------------ 4 files changed, 294 deletions(-) delete mode 100644 src/Core/Attributes/Api.php delete mode 100644 src/Core/Concerns/SdkResponse.php delete mode 100644 src/Core/Conversion/Contracts/ResponseConverter.php delete mode 100644 tests/Core/TestModel.php diff --git a/src/Core/Attributes/Api.php b/src/Core/Attributes/Api.php deleted file mode 100644 index 192fd09..0000000 --- a/src/Core/Attributes/Api.php +++ /dev/null @@ -1,66 +0,0 @@ -|Converter|string|null */ - public readonly Converter|string|null $type; - - /** @var array */ - private static array $enumConverters = []; - - /** - * @param class-string|Converter|string|null $type - * @param class-string<\BackedEnum>|Converter|null $enum - * @param class-string|Converter|null $union - * @param class-string|Converter|string|null $list - * @param class-string|Converter|string|null $map - */ - public function __construct( - public readonly ?string $apiName = null, - Converter|string|null $type = null, - Converter|string|null $enum = null, - Converter|string|null $union = null, - Converter|string|null $list = null, - Converter|string|null $map = null, - public readonly bool $nullable = false, - public readonly bool $optional = false, - ) { - $type ??= $union; - if (null !== $list) { - $type ??= new ListOf($list); - } - if (null !== $map) { - $type ??= new MapOf($map); - } - if (null !== $enum) { - $type ??= $enum instanceof Converter ? $enum : $this->getEnumConverter($enum); - } - - $this->type = $type; - } - - /** @property class-string<\BackedEnum> $enum */ - private function getEnumConverter(string $enum): Converter - { - if (!isset(self::$enumConverters[$enum])) { - $converter = new EnumOf(array_column($enum::cases(), 'value')); // @phpstan-ignore-line - self::$enumConverters[$enum] = $converter; - } - - return self::$enumConverters[$enum]; - } -} diff --git a/src/Core/Concerns/SdkResponse.php b/src/Core/Concerns/SdkResponse.php deleted file mode 100644 index 26fb402..0000000 --- a/src/Core/Concerns/SdkResponse.php +++ /dev/null @@ -1,29 +0,0 @@ -_rawResponse = $response; - $instance->__unserialize(Util::decodeContent($response)); // @phpstan-ignore-line - - return $instance; - } - - public function getRawResponse(): ?ResponseInterface - { - return $this->_rawResponse; - } -} diff --git a/src/Core/Conversion/Contracts/ResponseConverter.php b/src/Core/Conversion/Contracts/ResponseConverter.php deleted file mode 100644 index 1331c18..0000000 --- a/src/Core/Conversion/Contracts/ResponseConverter.php +++ /dev/null @@ -1,18 +0,0 @@ -> */ - use SdkModel; - - #[Required] - public string $name; - - #[Required('age_years')] - public int $ageYears; - - /** @var list|null */ - #[Optional] - public ?array $friends; - - #[Required] - public ?string $owner; - - /** - * @param list|null $friends - */ - public function __construct( - string $name, - int $ageYears, - ?string $owner, - ?array $friends = null, - ) { - $this->initialize(); - - $this->name = $name; - $this->ageYears = $ageYears; - $this->owner = $owner; - - null != $friends && $this->friends = $friends; - } -} - -/** - * @internal - * - * @coversNothing - */ -#[CoversNothing] -class TestModelTest extends TestCase -{ - #[Test] - public function testBasicGetAndSet(): void - { - $model = new TestModel( - name: 'Bob', - ageYears: 12, - owner: null, - ); - $this->assertEquals(12, $model->ageYears); - - ++$model->ageYears; - $this->assertEquals(13, $model->ageYears); - } - - #[Test] - public function testNullAccess(): void - { - $model = new TestModel( - name: 'Bob', - ageYears: 12, - owner: null, - ); - $this->assertNull($model->owner); - $this->assertNull($model->friends); - } - - #[Test] - public function testArrayGetAndSet(): void - { - $model = new TestModel( - name: 'Bob', - ageYears: 12, - owner: null, - ); - $model->friends ??= []; - $this->assertEquals([], $model->friends); - $model->friends[] = 'Alice'; - $this->assertEquals(['Alice'], $model->friends); - } - - #[Test] - public function testDiscernsBetweenNullAndUnset(): void - { - $modelUnsetFriends = new TestModel( - name: 'Bob', - ageYears: 12, - owner: null, - ); - $modelNullFriends = new TestModel( - name: 'bob', - ageYears: 12, - owner: null, - ); - $modelNullFriends->friends = null; - - $this->assertEquals(12, $modelUnsetFriends->ageYears); - $this->assertEquals(12, $modelNullFriends->ageYears); - - $this->assertTrue($modelUnsetFriends->offsetExists('ageYears')); - $this->assertTrue($modelNullFriends->offsetExists('ageYears')); - - $this->assertNull($modelUnsetFriends->friends); - $this->assertNull($modelNullFriends->friends); - - $this->assertFalse($modelUnsetFriends->offsetExists('friends')); - $this->assertTrue($modelNullFriends->offsetExists('friends')); - } - - #[Test] - public function testIssetOnOmittedProperties(): void - { - $model = new TestModel( - name: 'Bob', - ageYears: 12, - owner: null, - ); - $this->assertFalse(isset($model->owner)); - $this->assertFalse(isset($model->friends)); - } - - #[Test] - public function testSerializeBasicModel(): void - { - $model = new TestModel( - name: 'Bob', - ageYears: 12, - owner: 'Eve', - friends: ['Alice', 'Charlie'], - ); - $this->assertEquals( - '{"name":"Bob","age_years":12,"friends":["Alice","Charlie"],"owner":"Eve"}', - json_encode($model) - ); - } - - #[Test] - public function testSerializeModelWithOmittedProperties(): void - { - $model = new TestModel( - name: 'Bob', - ageYears: 12, - owner: null, - ); - $this->assertEquals( - '{"name":"Bob","age_years":12,"owner":null}', - json_encode($model) - ); - } - - #[Test] - public function testSerializeModelWithExplicitNull(): void - { - $model = new TestModel( - name: 'Bob', - ageYears: 12, - owner: null, - ); - $model->friends = null; - $this->assertEquals( - '{"name":"Bob","age_years":12,"friends":null,"owner":null}', - json_encode($model) - ); - } -} From 95004df5bf286d7fc8942781a6e69a56e6cefe53 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 06:00:59 +0000 Subject: [PATCH 17/29] feat: improved phpstan type annotations --- src/Sessions/Action.php | 2 +- src/Sessions/SessionActParams.php | 10 +++++----- src/Sessions/SessionActParams/Options.php | 4 ++-- src/Sessions/SessionActResponse.php | 4 ++-- src/Sessions/SessionActResponse/Data.php | 4 ++-- src/Sessions/SessionEndParams.php | 4 ++-- src/Sessions/SessionExecuteParams.php | 16 ++++++++-------- .../SessionExecuteParams/AgentConfig.php | 2 +- src/Sessions/SessionExecuteResponse.php | 4 ++-- src/Sessions/SessionExecuteResponse/Data.php | 4 ++-- .../SessionExecuteResponse/Data/Result.php | 6 +++--- src/Sessions/SessionExtractParams.php | 12 ++++++------ src/Sessions/SessionExtractParams/Options.php | 2 +- src/Sessions/SessionExtractResponse.php | 4 ++-- src/Sessions/SessionNavigateParams.php | 10 +++++----- src/Sessions/SessionNavigateParams/Options.php | 2 +- src/Sessions/SessionNavigateResponse.php | 4 ++-- src/Sessions/SessionObserveParams.php | 10 +++++----- src/Sessions/SessionObserveParams/Options.php | 2 +- src/Sessions/SessionObserveResponse.php | 4 ++-- src/Sessions/SessionStartParams.php | 16 ++++++++-------- src/Sessions/SessionStartParams/Browser.php | 6 +++--- .../SessionStartParams/Browser/LaunchOptions.php | 12 ++++++------ .../BrowserbaseSessionCreateParams.php | 10 +++++----- .../BrowserSettings.php | 12 ++++++------ .../BrowserSettings/Fingerprint.php | 14 +++++++------- .../ProxyConfigList/BrowserbaseProxyConfig.php | 4 ++-- src/Sessions/SessionStartResponse.php | 4 ++-- src/Sessions/StreamEvent.php | 4 +--- 29 files changed, 95 insertions(+), 97 deletions(-) diff --git a/src/Sessions/Action.php b/src/Sessions/Action.php index 6ddbf07..3b52526 100644 --- a/src/Sessions/Action.php +++ b/src/Sessions/Action.php @@ -74,7 +74,7 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param list $arguments + * @param list|null $arguments */ public static function with( string $description, diff --git a/src/Sessions/SessionActParams.php b/src/Sessions/SessionActParams.php index 4be2342..957a702 100644 --- a/src/Sessions/SessionActParams.php +++ b/src/Sessions/SessionActParams.php @@ -24,7 +24,7 @@ * @phpstan-type SessionActParamsShape = array{ * input: InputShape, * frameID?: string|null, - * options?: OptionsShape|null, + * options?: null|Options|OptionsShape, * xLanguage?: null|XLanguage|value-of, * xSDKVersion?: string|null, * xSentAt?: \DateTimeInterface|null, @@ -105,9 +105,9 @@ public function __construct() * You must use named parameters to construct any parameters with a default value. * * @param InputShape $input - * @param OptionsShape $options - * @param XLanguage|value-of $xLanguage - * @param XStreamResponse|value-of $xStreamResponse + * @param Options|OptionsShape|null $options + * @param XLanguage|value-of|null $xLanguage + * @param XStreamResponse|value-of|null $xStreamResponse */ public static function with( string|Action|array $input, @@ -157,7 +157,7 @@ public function withFrameID(string $frameID): self } /** - * @param OptionsShape $options + * @param Options|OptionsShape $options */ public function withOptions(Options|array $options): self { diff --git a/src/Sessions/SessionActParams/Options.php b/src/Sessions/SessionActParams/Options.php index 9326579..1cae53a 100644 --- a/src/Sessions/SessionActParams/Options.php +++ b/src/Sessions/SessionActParams/Options.php @@ -53,8 +53,8 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param ModelConfigShape $model - * @param array $variables + * @param ModelConfigShape|null $model + * @param array|null $variables */ public static function with( string|ModelConfigObject|array|null $model = null, diff --git a/src/Sessions/SessionActResponse.php b/src/Sessions/SessionActResponse.php index 086b152..c3ff087 100644 --- a/src/Sessions/SessionActResponse.php +++ b/src/Sessions/SessionActResponse.php @@ -54,7 +54,7 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param DataShape $data + * @param Data|DataShape $data */ public static function with(Data|array $data, bool $success): self { @@ -67,7 +67,7 @@ public static function with(Data|array $data, bool $success): self } /** - * @param DataShape $data + * @param Data|DataShape $data */ public function withData(Data|array $data): self { diff --git a/src/Sessions/SessionActResponse/Data.php b/src/Sessions/SessionActResponse/Data.php index 8322851..73af7f4 100644 --- a/src/Sessions/SessionActResponse/Data.php +++ b/src/Sessions/SessionActResponse/Data.php @@ -55,7 +55,7 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param ResultShape $result + * @param Result|ResultShape $result */ public static function with( Result|array $result, @@ -71,7 +71,7 @@ public static function with( } /** - * @param ResultShape $result + * @param Result|ResultShape $result */ public function withResult(Result|array $result): self { diff --git a/src/Sessions/SessionEndParams.php b/src/Sessions/SessionEndParams.php index 243b0dd..1528ec0 100644 --- a/src/Sessions/SessionEndParams.php +++ b/src/Sessions/SessionEndParams.php @@ -67,8 +67,8 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param XLanguage|value-of $xLanguage - * @param XStreamResponse|value-of $xStreamResponse + * @param XLanguage|value-of|null $xLanguage + * @param XStreamResponse|value-of|null $xStreamResponse */ public static function with( XLanguage|string|null $xLanguage = null, diff --git a/src/Sessions/SessionExecuteParams.php b/src/Sessions/SessionExecuteParams.php index b700f0a..c7e5e88 100644 --- a/src/Sessions/SessionExecuteParams.php +++ b/src/Sessions/SessionExecuteParams.php @@ -23,8 +23,8 @@ * @phpstan-import-type ExecuteOptionsShape from \Stagehand\Sessions\SessionExecuteParams\ExecuteOptions * * @phpstan-type SessionExecuteParamsShape = array{ - * agentConfig: AgentConfigShape, - * executeOptions: ExecuteOptionsShape, + * agentConfig: AgentConfig|AgentConfigShape, + * executeOptions: ExecuteOptions|ExecuteOptionsShape, * frameID?: string|null, * xLanguage?: null|XLanguage|value-of, * xSDKVersion?: string|null, @@ -102,10 +102,10 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param AgentConfigShape $agentConfig - * @param ExecuteOptionsShape $executeOptions - * @param XLanguage|value-of $xLanguage - * @param XStreamResponse|value-of $xStreamResponse + * @param AgentConfig|AgentConfigShape $agentConfig + * @param ExecuteOptions|ExecuteOptionsShape $executeOptions + * @param XLanguage|value-of|null $xLanguage + * @param XStreamResponse|value-of|null $xStreamResponse */ public static function with( AgentConfig|array $agentConfig, @@ -131,7 +131,7 @@ public static function with( } /** - * @param AgentConfigShape $agentConfig + * @param AgentConfig|AgentConfigShape $agentConfig */ public function withAgentConfig(AgentConfig|array $agentConfig): self { @@ -142,7 +142,7 @@ public function withAgentConfig(AgentConfig|array $agentConfig): self } /** - * @param ExecuteOptionsShape $executeOptions + * @param ExecuteOptions|ExecuteOptionsShape $executeOptions */ public function withExecuteOptions( ExecuteOptions|array $executeOptions diff --git a/src/Sessions/SessionExecuteParams/AgentConfig.php b/src/Sessions/SessionExecuteParams/AgentConfig.php index 54e981a..60f228b 100644 --- a/src/Sessions/SessionExecuteParams/AgentConfig.php +++ b/src/Sessions/SessionExecuteParams/AgentConfig.php @@ -49,7 +49,7 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param ModelConfigShape $model + * @param ModelConfigShape|null $model */ public static function with( ?bool $cua = null, diff --git a/src/Sessions/SessionExecuteResponse.php b/src/Sessions/SessionExecuteResponse.php index 99e7670..7f686d9 100644 --- a/src/Sessions/SessionExecuteResponse.php +++ b/src/Sessions/SessionExecuteResponse.php @@ -54,7 +54,7 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param DataShape $data + * @param Data|DataShape $data */ public static function with(Data|array $data, bool $success): self { @@ -67,7 +67,7 @@ public static function with(Data|array $data, bool $success): self } /** - * @param DataShape $data + * @param Data|DataShape $data */ public function withData(Data|array $data): self { diff --git a/src/Sessions/SessionExecuteResponse/Data.php b/src/Sessions/SessionExecuteResponse/Data.php index fe88bc4..1e26019 100644 --- a/src/Sessions/SessionExecuteResponse/Data.php +++ b/src/Sessions/SessionExecuteResponse/Data.php @@ -46,7 +46,7 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param ResultShape $result + * @param Result|ResultShape $result */ public static function with(Result|array $result): self { @@ -58,7 +58,7 @@ public static function with(Result|array $result): self } /** - * @param ResultShape $result + * @param Result|ResultShape $result */ public function withResult(Result|array $result): self { diff --git a/src/Sessions/SessionExecuteResponse/Data/Result.php b/src/Sessions/SessionExecuteResponse/Data/Result.php index c8f8e55..4efeb99 100644 --- a/src/Sessions/SessionExecuteResponse/Data/Result.php +++ b/src/Sessions/SessionExecuteResponse/Data/Result.php @@ -87,8 +87,8 @@ public function __construct() * You must use named parameters to construct any parameters with a default value. * * @param list $actions - * @param array $metadata - * @param UsageShape $usage + * @param array|null $metadata + * @param Usage|UsageShape|null $usage */ public static function with( array $actions, @@ -167,7 +167,7 @@ public function withMetadata(array $metadata): self } /** - * @param UsageShape $usage + * @param Usage|UsageShape $usage */ public function withUsage(Usage|array $usage): self { diff --git a/src/Sessions/SessionExtractParams.php b/src/Sessions/SessionExtractParams.php index 643418d..7c840bd 100644 --- a/src/Sessions/SessionExtractParams.php +++ b/src/Sessions/SessionExtractParams.php @@ -22,7 +22,7 @@ * @phpstan-type SessionExtractParamsShape = array{ * frameID?: string|null, * instruction?: string|null, - * options?: OptionsShape|null, + * options?: null|Options|OptionsShape, * schema?: array|null, * xLanguage?: null|XLanguage|value-of, * xSDKVersion?: string|null, @@ -97,10 +97,10 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param OptionsShape $options - * @param array $schema - * @param XLanguage|value-of $xLanguage - * @param XStreamResponse|value-of $xStreamResponse + * @param Options|OptionsShape|null $options + * @param array|null $schema + * @param XLanguage|value-of|null $xLanguage + * @param XStreamResponse|value-of|null $xStreamResponse */ public static function with( ?string $frameID = null, @@ -149,7 +149,7 @@ public function withInstruction(string $instruction): self } /** - * @param OptionsShape $options + * @param Options|OptionsShape $options */ public function withOptions(Options|array $options): self { diff --git a/src/Sessions/SessionExtractParams/Options.php b/src/Sessions/SessionExtractParams/Options.php index 18da4fd..b7946aa 100644 --- a/src/Sessions/SessionExtractParams/Options.php +++ b/src/Sessions/SessionExtractParams/Options.php @@ -49,7 +49,7 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param ModelConfigShape $model + * @param ModelConfigShape|null $model */ public static function with( string|ModelConfigObject|array|null $model = null, diff --git a/src/Sessions/SessionExtractResponse.php b/src/Sessions/SessionExtractResponse.php index e30a9bf..7b3caa3 100644 --- a/src/Sessions/SessionExtractResponse.php +++ b/src/Sessions/SessionExtractResponse.php @@ -54,7 +54,7 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param DataShape $data + * @param Data|DataShape $data */ public static function with(Data|array $data, bool $success): self { @@ -67,7 +67,7 @@ public static function with(Data|array $data, bool $success): self } /** - * @param DataShape $data + * @param Data|DataShape $data */ public function withData(Data|array $data): self { diff --git a/src/Sessions/SessionNavigateParams.php b/src/Sessions/SessionNavigateParams.php index d4a359a..97fb1a5 100644 --- a/src/Sessions/SessionNavigateParams.php +++ b/src/Sessions/SessionNavigateParams.php @@ -23,7 +23,7 @@ * @phpstan-type SessionNavigateParamsShape = array{ * url: string, * frameID?: string|null, - * options?: OptionsShape|null, + * options?: null|Options|OptionsShape, * streamResponse?: bool|null, * xLanguage?: null|XLanguage|value-of, * xSDKVersion?: string|null, @@ -110,9 +110,9 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param OptionsShape $options - * @param XLanguage|value-of $xLanguage - * @param XStreamResponse|value-of $xStreamResponse + * @param Options|OptionsShape|null $options + * @param XLanguage|value-of|null $xLanguage + * @param XStreamResponse|value-of|null $xStreamResponse */ public static function with( string $url, @@ -162,7 +162,7 @@ public function withFrameID(string $frameID): self } /** - * @param OptionsShape $options + * @param Options|OptionsShape $options */ public function withOptions(Options|array $options): self { diff --git a/src/Sessions/SessionNavigateParams/Options.php b/src/Sessions/SessionNavigateParams/Options.php index a94861c..be4e190 100644 --- a/src/Sessions/SessionNavigateParams/Options.php +++ b/src/Sessions/SessionNavigateParams/Options.php @@ -51,7 +51,7 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param WaitUntil|value-of $waitUntil + * @param WaitUntil|value-of|null $waitUntil */ public static function with( ?string $referer = null, diff --git a/src/Sessions/SessionNavigateResponse.php b/src/Sessions/SessionNavigateResponse.php index a918959..30852f2 100644 --- a/src/Sessions/SessionNavigateResponse.php +++ b/src/Sessions/SessionNavigateResponse.php @@ -54,7 +54,7 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param DataShape $data + * @param Data|DataShape $data */ public static function with(Data|array $data, bool $success): self { @@ -67,7 +67,7 @@ public static function with(Data|array $data, bool $success): self } /** - * @param DataShape $data + * @param Data|DataShape $data */ public function withData(Data|array $data): self { diff --git a/src/Sessions/SessionObserveParams.php b/src/Sessions/SessionObserveParams.php index b9aba90..c344597 100644 --- a/src/Sessions/SessionObserveParams.php +++ b/src/Sessions/SessionObserveParams.php @@ -22,7 +22,7 @@ * @phpstan-type SessionObserveParamsShape = array{ * frameID?: string|null, * instruction?: string|null, - * options?: OptionsShape|null, + * options?: null|Options|OptionsShape, * xLanguage?: null|XLanguage|value-of, * xSDKVersion?: string|null, * xSentAt?: \DateTimeInterface|null, @@ -88,9 +88,9 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param OptionsShape $options - * @param XLanguage|value-of $xLanguage - * @param XStreamResponse|value-of $xStreamResponse + * @param Options|OptionsShape|null $options + * @param XLanguage|value-of|null $xLanguage + * @param XStreamResponse|value-of|null $xStreamResponse */ public static function with( ?string $frameID = null, @@ -137,7 +137,7 @@ public function withInstruction(string $instruction): self } /** - * @param OptionsShape $options + * @param Options|OptionsShape $options */ public function withOptions(Options|array $options): self { diff --git a/src/Sessions/SessionObserveParams/Options.php b/src/Sessions/SessionObserveParams/Options.php index f76bf82..19644b3 100644 --- a/src/Sessions/SessionObserveParams/Options.php +++ b/src/Sessions/SessionObserveParams/Options.php @@ -49,7 +49,7 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param ModelConfigShape $model + * @param ModelConfigShape|null $model */ public static function with( string|ModelConfigObject|array|null $model = null, diff --git a/src/Sessions/SessionObserveResponse.php b/src/Sessions/SessionObserveResponse.php index fa53508..e8a9b79 100644 --- a/src/Sessions/SessionObserveResponse.php +++ b/src/Sessions/SessionObserveResponse.php @@ -54,7 +54,7 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param DataShape $data + * @param Data|DataShape $data */ public static function with(Data|array $data, bool $success): self { @@ -67,7 +67,7 @@ public static function with(Data|array $data, bool $success): self } /** - * @param DataShape $data + * @param Data|DataShape $data */ public function withData(Data|array $data): self { diff --git a/src/Sessions/SessionStartParams.php b/src/Sessions/SessionStartParams.php index 06273b7..f6a22e9 100644 --- a/src/Sessions/SessionStartParams.php +++ b/src/Sessions/SessionStartParams.php @@ -25,8 +25,8 @@ * @phpstan-type SessionStartParamsShape = array{ * modelName: string, * actTimeoutMs?: float|null, - * browser?: BrowserShape|null, - * browserbaseSessionCreateParams?: BrowserbaseSessionCreateParamsShape|null, + * browser?: null|Browser|BrowserShape, + * browserbaseSessionCreateParams?: null|BrowserbaseSessionCreateParams|BrowserbaseSessionCreateParamsShape, * browserbaseSessionID?: string|null, * debugDom?: bool|null, * domSettleTimeoutMs?: float|null, @@ -156,10 +156,10 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param BrowserShape $browser - * @param BrowserbaseSessionCreateParamsShape $browserbaseSessionCreateParams - * @param XLanguage|value-of $xLanguage - * @param XStreamResponse|value-of $xStreamResponse + * @param Browser|BrowserShape|null $browser + * @param BrowserbaseSessionCreateParams|BrowserbaseSessionCreateParamsShape|null $browserbaseSessionCreateParams + * @param XLanguage|value-of|null $xLanguage + * @param XStreamResponse|value-of|null $xStreamResponse */ public static function with( string $modelName, @@ -225,7 +225,7 @@ public function withActTimeoutMs(float $actTimeoutMs): self } /** - * @param BrowserShape $browser + * @param Browser|BrowserShape $browser */ public function withBrowser(Browser|array $browser): self { @@ -236,7 +236,7 @@ public function withBrowser(Browser|array $browser): self } /** - * @param BrowserbaseSessionCreateParamsShape $browserbaseSessionCreateParams + * @param BrowserbaseSessionCreateParams|BrowserbaseSessionCreateParamsShape $browserbaseSessionCreateParams */ public function withBrowserbaseSessionCreateParams( BrowserbaseSessionCreateParams|array $browserbaseSessionCreateParams diff --git a/src/Sessions/SessionStartParams/Browser.php b/src/Sessions/SessionStartParams/Browser.php index 90c9bd4..b4ab955 100644 --- a/src/Sessions/SessionStartParams/Browser.php +++ b/src/Sessions/SessionStartParams/Browser.php @@ -51,8 +51,8 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param LaunchOptionsShape $launchOptions - * @param Type|value-of $type + * @param LaunchOptions|LaunchOptionsShape|null $launchOptions + * @param Type|value-of|null $type */ public static function with( ?string $cdpURL = null, @@ -80,7 +80,7 @@ public function withCdpURL(string $cdpURL): self } /** - * @param LaunchOptionsShape $launchOptions + * @param LaunchOptions|LaunchOptionsShape $launchOptions */ public function withLaunchOptions(LaunchOptions|array $launchOptions): self { diff --git a/src/Sessions/SessionStartParams/Browser/LaunchOptions.php b/src/Sessions/SessionStartParams/Browser/LaunchOptions.php index 292c049..d2fb2b7 100644 --- a/src/Sessions/SessionStartParams/Browser/LaunchOptions.php +++ b/src/Sessions/SessionStartParams/Browser/LaunchOptions.php @@ -108,10 +108,10 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param list $args - * @param IgnoreDefaultArgsShape $ignoreDefaultArgs - * @param ProxyShape $proxy - * @param ViewportShape $viewport + * @param list|null $args + * @param IgnoreDefaultArgsShape|null $ignoreDefaultArgs + * @param Proxy|ProxyShape|null $proxy + * @param Viewport|ViewportShape|null $viewport */ public static function with( ?bool $acceptDownloads = null, @@ -284,7 +284,7 @@ public function withPreserveUserDataDir(bool $preserveUserDataDir): self } /** - * @param ProxyShape $proxy + * @param Proxy|ProxyShape $proxy */ public function withProxy(Proxy|array $proxy): self { @@ -303,7 +303,7 @@ public function withUserDataDir(string $userDataDir): self } /** - * @param ViewportShape $viewport + * @param Viewport|ViewportShape $viewport */ public function withViewport(Viewport|array $viewport): self { diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams.php index 60cbb6b..bd293e7 100644 --- a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams.php +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams.php @@ -70,10 +70,10 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param BrowserSettingsShape $browserSettings - * @param ProxiesShape $proxies - * @param Region|value-of $region - * @param array $userMetadata + * @param BrowserSettings|BrowserSettingsShape|null $browserSettings + * @param ProxiesShape|null $proxies + * @param Region|value-of|null $region + * @param array|null $userMetadata */ public static function with( BrowserSettings|array|null $browserSettings = null, @@ -100,7 +100,7 @@ public static function with( } /** - * @param BrowserSettingsShape $browserSettings + * @param BrowserSettings|BrowserSettingsShape $browserSettings */ public function withBrowserSettings( BrowserSettings|array $browserSettings diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings.php index 4c21ce5..6014c60 100644 --- a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings.php +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings.php @@ -70,9 +70,9 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param ContextShape $context - * @param FingerprintShape $fingerprint - * @param ViewportShape $viewport + * @param Context|ContextShape|null $context + * @param Fingerprint|FingerprintShape|null $fingerprint + * @param Viewport|ViewportShape|null $viewport */ public static function with( ?bool $advancedStealth = null, @@ -117,7 +117,7 @@ public function withBlockAds(bool $blockAds): self } /** - * @param ContextShape $context + * @param Context|ContextShape $context */ public function withContext(Context|array $context): self { @@ -136,7 +136,7 @@ public function withExtensionID(string $extensionID): self } /** - * @param FingerprintShape $fingerprint + * @param Fingerprint|FingerprintShape $fingerprint */ public function withFingerprint(Fingerprint|array $fingerprint): self { @@ -171,7 +171,7 @@ public function withSolveCaptchas(bool $solveCaptchas): self } /** - * @param ViewportShape $viewport + * @param Viewport|ViewportShape $viewport */ public function withViewport(Viewport|array $viewport): self { diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Fingerprint.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Fingerprint.php index 831a5e8..e757711 100644 --- a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Fingerprint.php +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/BrowserSettings/Fingerprint.php @@ -63,12 +63,12 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param list> $browsers - * @param list> $devices - * @param HTTPVersion|value-of $httpVersion - * @param list $locales - * @param list> $operatingSystems - * @param ScreenShape $screen + * @param list>|null $browsers + * @param list>|null $devices + * @param HTTPVersion|value-of|null $httpVersion + * @param list|null $locales + * @param list>|null $operatingSystems + * @param Screen|ScreenShape|null $screen */ public static function with( ?array $browsers = null, @@ -146,7 +146,7 @@ public function withOperatingSystems(array $operatingSystems): self } /** - * @param ScreenShape $screen + * @param Screen|ScreenShape $screen */ public function withScreen(Screen|array $screen): self { diff --git a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/ProxyConfigList/BrowserbaseProxyConfig.php b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/ProxyConfigList/BrowserbaseProxyConfig.php index c939391..3aa53a2 100644 --- a/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/ProxyConfigList/BrowserbaseProxyConfig.php +++ b/src/Sessions/SessionStartParams/BrowserbaseSessionCreateParams/Proxies/ProxyConfigList/BrowserbaseProxyConfig.php @@ -44,7 +44,7 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param GeolocationShape $geolocation + * @param Geolocation|GeolocationShape|null $geolocation */ public static function with( ?string $domainPattern = null, @@ -67,7 +67,7 @@ public function withDomainPattern(string $domainPattern): self } /** - * @param GeolocationShape $geolocation + * @param Geolocation|GeolocationShape $geolocation */ public function withGeolocation(Geolocation|array $geolocation): self { diff --git a/src/Sessions/SessionStartResponse.php b/src/Sessions/SessionStartResponse.php index 4d78ad2..8a4fc97 100644 --- a/src/Sessions/SessionStartResponse.php +++ b/src/Sessions/SessionStartResponse.php @@ -54,7 +54,7 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param DataShape $data + * @param Data|DataShape $data */ public static function with(Data|array $data, bool $success): self { @@ -67,7 +67,7 @@ public static function with(Data|array $data, bool $success): self } /** - * @param DataShape $data + * @param Data|DataShape $data */ public function withData(Data|array $data): self { diff --git a/src/Sessions/StreamEvent.php b/src/Sessions/StreamEvent.php index ba75c87..14261ce 100644 --- a/src/Sessions/StreamEvent.php +++ b/src/Sessions/StreamEvent.php @@ -17,9 +17,7 @@ * @phpstan-import-type DataShape from \Stagehand\Sessions\StreamEvent\Data * * @phpstan-type StreamEventShape = array{ - * id: string, - * data: StreamEventSystemDataOutput|StreamEventLogDataOutput|DataShape, - * type: Type|value-of, + * id: string, data: DataShape, type: Type|value-of * } */ final class StreamEvent implements BaseModel From 96c0813ae699b18ce127aa6f693009cc2f3d63b2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 19 Dec 2025 05:33:18 +0000 Subject: [PATCH 18/29] chore(internal): codegen related update --- src/Core/Attributes/Api.php | 66 +++++++ src/Core/Concerns/SdkResponse.php | 29 +++ .../Contracts/ResponseConverter.php | 18 ++ tests/Core/TestModel.php | 181 ++++++++++++++++++ 4 files changed, 294 insertions(+) create mode 100644 src/Core/Attributes/Api.php create mode 100644 src/Core/Concerns/SdkResponse.php create mode 100644 src/Core/Conversion/Contracts/ResponseConverter.php create mode 100644 tests/Core/TestModel.php diff --git a/src/Core/Attributes/Api.php b/src/Core/Attributes/Api.php new file mode 100644 index 0000000..192fd09 --- /dev/null +++ b/src/Core/Attributes/Api.php @@ -0,0 +1,66 @@ +|Converter|string|null */ + public readonly Converter|string|null $type; + + /** @var array */ + private static array $enumConverters = []; + + /** + * @param class-string|Converter|string|null $type + * @param class-string<\BackedEnum>|Converter|null $enum + * @param class-string|Converter|null $union + * @param class-string|Converter|string|null $list + * @param class-string|Converter|string|null $map + */ + public function __construct( + public readonly ?string $apiName = null, + Converter|string|null $type = null, + Converter|string|null $enum = null, + Converter|string|null $union = null, + Converter|string|null $list = null, + Converter|string|null $map = null, + public readonly bool $nullable = false, + public readonly bool $optional = false, + ) { + $type ??= $union; + if (null !== $list) { + $type ??= new ListOf($list); + } + if (null !== $map) { + $type ??= new MapOf($map); + } + if (null !== $enum) { + $type ??= $enum instanceof Converter ? $enum : $this->getEnumConverter($enum); + } + + $this->type = $type; + } + + /** @property class-string<\BackedEnum> $enum */ + private function getEnumConverter(string $enum): Converter + { + if (!isset(self::$enumConverters[$enum])) { + $converter = new EnumOf(array_column($enum::cases(), 'value')); // @phpstan-ignore-line + self::$enumConverters[$enum] = $converter; + } + + return self::$enumConverters[$enum]; + } +} diff --git a/src/Core/Concerns/SdkResponse.php b/src/Core/Concerns/SdkResponse.php new file mode 100644 index 0000000..26fb402 --- /dev/null +++ b/src/Core/Concerns/SdkResponse.php @@ -0,0 +1,29 @@ +_rawResponse = $response; + $instance->__unserialize(Util::decodeContent($response)); // @phpstan-ignore-line + + return $instance; + } + + public function getRawResponse(): ?ResponseInterface + { + return $this->_rawResponse; + } +} diff --git a/src/Core/Conversion/Contracts/ResponseConverter.php b/src/Core/Conversion/Contracts/ResponseConverter.php new file mode 100644 index 0000000..1331c18 --- /dev/null +++ b/src/Core/Conversion/Contracts/ResponseConverter.php @@ -0,0 +1,18 @@ +> */ + use SdkModel; + + #[Required] + public string $name; + + #[Required('age_years')] + public int $ageYears; + + /** @var list|null */ + #[Optional] + public ?array $friends; + + #[Required] + public ?string $owner; + + /** + * @param list|null $friends + */ + public function __construct( + string $name, + int $ageYears, + ?string $owner, + ?array $friends = null, + ) { + $this->initialize(); + + $this->name = $name; + $this->ageYears = $ageYears; + $this->owner = $owner; + + null != $friends && $this->friends = $friends; + } +} + +/** + * @internal + * + * @coversNothing + */ +#[CoversNothing] +class TestModelTest extends TestCase +{ + #[Test] + public function testBasicGetAndSet(): void + { + $model = new TestModel( + name: 'Bob', + ageYears: 12, + owner: null, + ); + $this->assertEquals(12, $model->ageYears); + + ++$model->ageYears; + $this->assertEquals(13, $model->ageYears); + } + + #[Test] + public function testNullAccess(): void + { + $model = new TestModel( + name: 'Bob', + ageYears: 12, + owner: null, + ); + $this->assertNull($model->owner); + $this->assertNull($model->friends); + } + + #[Test] + public function testArrayGetAndSet(): void + { + $model = new TestModel( + name: 'Bob', + ageYears: 12, + owner: null, + ); + $model->friends ??= []; + $this->assertEquals([], $model->friends); + $model->friends[] = 'Alice'; + $this->assertEquals(['Alice'], $model->friends); + } + + #[Test] + public function testDiscernsBetweenNullAndUnset(): void + { + $modelUnsetFriends = new TestModel( + name: 'Bob', + ageYears: 12, + owner: null, + ); + $modelNullFriends = new TestModel( + name: 'bob', + ageYears: 12, + owner: null, + ); + $modelNullFriends->friends = null; + + $this->assertEquals(12, $modelUnsetFriends->ageYears); + $this->assertEquals(12, $modelNullFriends->ageYears); + + $this->assertTrue($modelUnsetFriends->offsetExists('ageYears')); + $this->assertTrue($modelNullFriends->offsetExists('ageYears')); + + $this->assertNull($modelUnsetFriends->friends); + $this->assertNull($modelNullFriends->friends); + + $this->assertFalse($modelUnsetFriends->offsetExists('friends')); + $this->assertTrue($modelNullFriends->offsetExists('friends')); + } + + #[Test] + public function testIssetOnOmittedProperties(): void + { + $model = new TestModel( + name: 'Bob', + ageYears: 12, + owner: null, + ); + $this->assertFalse(isset($model->owner)); + $this->assertFalse(isset($model->friends)); + } + + #[Test] + public function testSerializeBasicModel(): void + { + $model = new TestModel( + name: 'Bob', + ageYears: 12, + owner: 'Eve', + friends: ['Alice', 'Charlie'], + ); + $this->assertEquals( + '{"name":"Bob","age_years":12,"friends":["Alice","Charlie"],"owner":"Eve"}', + json_encode($model) + ); + } + + #[Test] + public function testSerializeModelWithOmittedProperties(): void + { + $model = new TestModel( + name: 'Bob', + ageYears: 12, + owner: null, + ); + $this->assertEquals( + '{"name":"Bob","age_years":12,"owner":null}', + json_encode($model) + ); + } + + #[Test] + public function testSerializeModelWithExplicitNull(): void + { + $model = new TestModel( + name: 'Bob', + ageYears: 12, + owner: null, + ); + $model->friends = null; + $this->assertEquals( + '{"name":"Bob","age_years":12,"friends":null,"owner":null}', + json_encode($model) + ); + } +} From 79b8f76ee409f5a35cc742496109e803138554b1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 19 Dec 2025 05:34:14 +0000 Subject: [PATCH 19/29] chore(internal): codegen related update --- src/Core/Attributes/Api.php | 66 ------- src/Core/Concerns/SdkResponse.php | 29 --- .../Contracts/ResponseConverter.php | 18 -- tests/Core/TestModel.php | 181 ------------------ 4 files changed, 294 deletions(-) delete mode 100644 src/Core/Attributes/Api.php delete mode 100644 src/Core/Concerns/SdkResponse.php delete mode 100644 src/Core/Conversion/Contracts/ResponseConverter.php delete mode 100644 tests/Core/TestModel.php diff --git a/src/Core/Attributes/Api.php b/src/Core/Attributes/Api.php deleted file mode 100644 index 192fd09..0000000 --- a/src/Core/Attributes/Api.php +++ /dev/null @@ -1,66 +0,0 @@ -|Converter|string|null */ - public readonly Converter|string|null $type; - - /** @var array */ - private static array $enumConverters = []; - - /** - * @param class-string|Converter|string|null $type - * @param class-string<\BackedEnum>|Converter|null $enum - * @param class-string|Converter|null $union - * @param class-string|Converter|string|null $list - * @param class-string|Converter|string|null $map - */ - public function __construct( - public readonly ?string $apiName = null, - Converter|string|null $type = null, - Converter|string|null $enum = null, - Converter|string|null $union = null, - Converter|string|null $list = null, - Converter|string|null $map = null, - public readonly bool $nullable = false, - public readonly bool $optional = false, - ) { - $type ??= $union; - if (null !== $list) { - $type ??= new ListOf($list); - } - if (null !== $map) { - $type ??= new MapOf($map); - } - if (null !== $enum) { - $type ??= $enum instanceof Converter ? $enum : $this->getEnumConverter($enum); - } - - $this->type = $type; - } - - /** @property class-string<\BackedEnum> $enum */ - private function getEnumConverter(string $enum): Converter - { - if (!isset(self::$enumConverters[$enum])) { - $converter = new EnumOf(array_column($enum::cases(), 'value')); // @phpstan-ignore-line - self::$enumConverters[$enum] = $converter; - } - - return self::$enumConverters[$enum]; - } -} diff --git a/src/Core/Concerns/SdkResponse.php b/src/Core/Concerns/SdkResponse.php deleted file mode 100644 index 26fb402..0000000 --- a/src/Core/Concerns/SdkResponse.php +++ /dev/null @@ -1,29 +0,0 @@ -_rawResponse = $response; - $instance->__unserialize(Util::decodeContent($response)); // @phpstan-ignore-line - - return $instance; - } - - public function getRawResponse(): ?ResponseInterface - { - return $this->_rawResponse; - } -} diff --git a/src/Core/Conversion/Contracts/ResponseConverter.php b/src/Core/Conversion/Contracts/ResponseConverter.php deleted file mode 100644 index 1331c18..0000000 --- a/src/Core/Conversion/Contracts/ResponseConverter.php +++ /dev/null @@ -1,18 +0,0 @@ -> */ - use SdkModel; - - #[Required] - public string $name; - - #[Required('age_years')] - public int $ageYears; - - /** @var list|null */ - #[Optional] - public ?array $friends; - - #[Required] - public ?string $owner; - - /** - * @param list|null $friends - */ - public function __construct( - string $name, - int $ageYears, - ?string $owner, - ?array $friends = null, - ) { - $this->initialize(); - - $this->name = $name; - $this->ageYears = $ageYears; - $this->owner = $owner; - - null != $friends && $this->friends = $friends; - } -} - -/** - * @internal - * - * @coversNothing - */ -#[CoversNothing] -class TestModelTest extends TestCase -{ - #[Test] - public function testBasicGetAndSet(): void - { - $model = new TestModel( - name: 'Bob', - ageYears: 12, - owner: null, - ); - $this->assertEquals(12, $model->ageYears); - - ++$model->ageYears; - $this->assertEquals(13, $model->ageYears); - } - - #[Test] - public function testNullAccess(): void - { - $model = new TestModel( - name: 'Bob', - ageYears: 12, - owner: null, - ); - $this->assertNull($model->owner); - $this->assertNull($model->friends); - } - - #[Test] - public function testArrayGetAndSet(): void - { - $model = new TestModel( - name: 'Bob', - ageYears: 12, - owner: null, - ); - $model->friends ??= []; - $this->assertEquals([], $model->friends); - $model->friends[] = 'Alice'; - $this->assertEquals(['Alice'], $model->friends); - } - - #[Test] - public function testDiscernsBetweenNullAndUnset(): void - { - $modelUnsetFriends = new TestModel( - name: 'Bob', - ageYears: 12, - owner: null, - ); - $modelNullFriends = new TestModel( - name: 'bob', - ageYears: 12, - owner: null, - ); - $modelNullFriends->friends = null; - - $this->assertEquals(12, $modelUnsetFriends->ageYears); - $this->assertEquals(12, $modelNullFriends->ageYears); - - $this->assertTrue($modelUnsetFriends->offsetExists('ageYears')); - $this->assertTrue($modelNullFriends->offsetExists('ageYears')); - - $this->assertNull($modelUnsetFriends->friends); - $this->assertNull($modelNullFriends->friends); - - $this->assertFalse($modelUnsetFriends->offsetExists('friends')); - $this->assertTrue($modelNullFriends->offsetExists('friends')); - } - - #[Test] - public function testIssetOnOmittedProperties(): void - { - $model = new TestModel( - name: 'Bob', - ageYears: 12, - owner: null, - ); - $this->assertFalse(isset($model->owner)); - $this->assertFalse(isset($model->friends)); - } - - #[Test] - public function testSerializeBasicModel(): void - { - $model = new TestModel( - name: 'Bob', - ageYears: 12, - owner: 'Eve', - friends: ['Alice', 'Charlie'], - ); - $this->assertEquals( - '{"name":"Bob","age_years":12,"friends":["Alice","Charlie"],"owner":"Eve"}', - json_encode($model) - ); - } - - #[Test] - public function testSerializeModelWithOmittedProperties(): void - { - $model = new TestModel( - name: 'Bob', - ageYears: 12, - owner: null, - ); - $this->assertEquals( - '{"name":"Bob","age_years":12,"owner":null}', - json_encode($model) - ); - } - - #[Test] - public function testSerializeModelWithExplicitNull(): void - { - $model = new TestModel( - name: 'Bob', - ageYears: 12, - owner: null, - ); - $model->friends = null; - $this->assertEquals( - '{"name":"Bob","age_years":12,"friends":null,"owner":null}', - json_encode($model) - ); - } -} From 68fe598df0ac0f73aa8806ed4730bd4c479f54a6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 19 Dec 2025 23:36:37 +0000 Subject: [PATCH 20/29] feat(api): manual updates --- .stats.yml | 4 +- src/ServiceContracts/SessionsContract.php | 81 ++++++--- src/Services/SessionsRawService.php | 70 ++++++-- src/Services/SessionsService.php | 82 ++++++--- src/Sessions/Action.php | 20 +++ .../ModelConfig/ModelConfigObject.php | 33 +++- .../ModelConfigObject/Provider.php | 19 +++ .../SessionActResponse/Data/Result.php | 4 +- .../SessionActResponse/Data/Result/Action.php | 161 ++++++++++++++++++ .../SessionExecuteParams/AgentConfig.php | 30 +++- .../AgentConfig/Provider.php | 19 +++ src/Sessions/SessionObserveResponse/Data.php | 14 +- .../SessionObserveResponse/Data/Result.php | 161 ++++++++++++++++++ src/Sessions/SessionStartParams.php | 40 +++-- src/Sessions/SessionStartParams/Verbose.php | 17 ++ src/Sessions/SessionStartResponse/Data.php | 38 +++-- src/Sessions/StreamEvent.php | 2 +- tests/Services/SessionsTest.php | 6 +- 18 files changed, 692 insertions(+), 109 deletions(-) create mode 100644 src/Sessions/ModelConfig/ModelConfigObject/Provider.php create mode 100644 src/Sessions/SessionActResponse/Data/Result/Action.php create mode 100644 src/Sessions/SessionExecuteParams/AgentConfig/Provider.php create mode 100644 src/Sessions/SessionObserveResponse/Data/Result.php create mode 100644 src/Sessions/SessionStartParams/Verbose.php diff --git a/.stats.yml b/.stats.yml index 5dba58c..d90df61 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-f7d6b6489159f611a2bfdc267ce0a6fc0455bed1ffa0c310044baaa5d8381b9b.yml -openapi_spec_hash: cd88d8068abfde8382da0bed674e440c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-4fb17cafc413ae3d575e3268602b01d2d0e9ebeb734a41b6086b3353ff0d2523.yml +openapi_spec_hash: 8d48d8564849246f6f14d900c6c5f60c config_hash: 5c69fb596588b8ace08203858518c149 diff --git a/src/ServiceContracts/SessionsContract.php b/src/ServiceContracts/SessionsContract.php index 91e4699..262f72c 100644 --- a/src/ServiceContracts/SessionsContract.php +++ b/src/ServiceContracts/SessionsContract.php @@ -7,7 +7,7 @@ use Stagehand\Core\Contracts\BaseStream; use Stagehand\Core\Exceptions\APIException; use Stagehand\RequestOptions; -use Stagehand\Sessions\Action; +use Stagehand\Sessions\ModelConfig\ModelConfigObject\Provider; use Stagehand\Sessions\SessionActParams\XLanguage; use Stagehand\Sessions\SessionActParams\XStreamResponse; use Stagehand\Sessions\SessionActResponse; @@ -23,6 +23,7 @@ use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\HTTPVersion; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\OperatingSystem; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Region; +use Stagehand\Sessions\SessionStartParams\Verbose; use Stagehand\Sessions\SessionStartResponse; use Stagehand\Sessions\StreamEvent; @@ -36,11 +37,17 @@ interface SessionsContract * description: string, * selector: string, * arguments?: list, + * backendNodeID?: float, * method?: string, - * }|Action $input Body param: Natural language instruction or Action object + * } $input Body param: Natural language instruction or Action object * @param string $frameID Body param: Target frame ID for the action * @param array{ - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, * timeout?: float, * variables?: array, * } $options Body param: @@ -53,7 +60,7 @@ interface SessionsContract */ public function act( string $id, - string|array|Action $input, + string|array $input, ?string $frameID = null, ?array $options = null, string|XLanguage|null $xLanguage = null, @@ -71,11 +78,17 @@ public function act( * description: string, * selector: string, * arguments?: list, + * backendNodeID?: float, * method?: string, - * }|Action $input Body param: Natural language instruction or Action object + * } $input Body param: Natural language instruction or Action object * @param string $frameID Body param: Target frame ID for the action * @param array{ - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, * timeout?: float, * variables?: array, * } $options Body param: @@ -90,7 +103,7 @@ public function act( */ public function actStream( string $id, - string|array|Action $input, + string|array $input, ?string $frameID = null, ?array $options = null, string|XLanguage|null $xLanguage = null, @@ -126,7 +139,13 @@ public function end( * @param string $id Path param: Unique session identifier * @param array{ * cua?: bool, - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|\Stagehand\Sessions\SessionExecuteParams\AgentConfig\Provider, * systemPrompt?: string, * } $agentConfig Body param: * @param array{ @@ -158,7 +177,13 @@ public function execute( * @param string $id Path param: Unique session identifier * @param array{ * cua?: bool, - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|\Stagehand\Sessions\SessionExecuteParams\AgentConfig\Provider, * systemPrompt?: string, * } $agentConfig Body param: * @param array{ @@ -193,7 +218,12 @@ public function executeStream( * @param string $frameID Body param: Target frame ID for the extraction * @param string $instruction Body param: Natural language instruction for what to extract * @param array{ - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, * selector?: string, * timeout?: float, * } $options Body param: @@ -225,7 +255,12 @@ public function extract( * @param string $frameID Body param: Target frame ID for the extraction * @param string $instruction Body param: Natural language instruction for what to extract * @param array{ - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, * selector?: string, * timeout?: float, * } $options Body param: @@ -291,7 +326,12 @@ public function navigate( * @param string $frameID Body param: Target frame ID for the observation * @param string $instruction Body param: Natural language instruction for what actions to find * @param array{ - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, * selector?: string, * timeout?: float, * } $options Body param: @@ -321,7 +361,12 @@ public function observe( * @param string $frameID Body param: Target frame ID for the observation * @param string $instruction Body param: Natural language instruction for what actions to find * @param array{ - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, * selector?: string, * timeout?: float, * } $options Body param: @@ -350,7 +395,7 @@ public function observeStream( * @api * * @param string $modelName Body param: Model name to use for AI operations - * @param float $actTimeoutMs Body param: Timeout in ms for act operations + * @param float $actTimeoutMs Body param: Timeout in ms for act operations (deprecated, v2 only) * @param array{ * cdpURL?: string, * launchOptions?: array{ @@ -407,13 +452,12 @@ public function observeStream( * userMetadata?: array, * } $browserbaseSessionCreateParams Body param: * @param string $browserbaseSessionID Body param: Existing Browserbase session ID to resume - * @param bool $debugDom Body param: * @param float $domSettleTimeoutMs Body param: Timeout in ms to wait for DOM to settle * @param bool $experimental Body param: * @param bool $selfHeal Body param: Enable self-healing for failed actions * @param string $systemPrompt Body param: Custom system prompt for AI operations - * @param int $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) - * @param bool $waitForCaptchaSolves Body param: + * @param '0'|'1'|'2'|Verbose $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) + * @param bool $waitForCaptchaSolves Body param: Wait for captcha solves (deprecated, v2 only) * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionStartParams\XLanguage $xLanguage Header param: Client SDK language * @param string $xSDKVersion Header param: Version of the Stagehand SDK * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent @@ -427,12 +471,11 @@ public function start( ?array $browser = null, ?array $browserbaseSessionCreateParams = null, ?string $browserbaseSessionID = null, - ?bool $debugDom = null, ?float $domSettleTimeoutMs = null, ?bool $experimental = null, ?bool $selfHeal = null, ?string $systemPrompt = null, - ?int $verbose = null, + string|Verbose|null $verbose = null, ?bool $waitForCaptchaSolves = null, string|\Stagehand\Sessions\SessionStartParams\XLanguage|null $xLanguage = null, ?string $xSDKVersion = null, diff --git a/src/Services/SessionsRawService.php b/src/Services/SessionsRawService.php index c84b4f2..a56604d 100644 --- a/src/Services/SessionsRawService.php +++ b/src/Services/SessionsRawService.php @@ -11,7 +11,7 @@ use Stagehand\Core\Util; use Stagehand\RequestOptions; use Stagehand\ServiceContracts\SessionsRawContract; -use Stagehand\Sessions\Action; +use Stagehand\Sessions\ModelConfig\ModelConfigObject\Provider; use Stagehand\Sessions\SessionActParams; use Stagehand\Sessions\SessionActResponse; use Stagehand\Sessions\SessionEndParams; @@ -31,6 +31,7 @@ use Stagehand\Sessions\SessionStartParams\Browser\Type; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\HTTPVersion; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Region; +use Stagehand\Sessions\SessionStartParams\Verbose; use Stagehand\Sessions\SessionStartResponse; use Stagehand\Sessions\StreamEvent; use Stagehand\SSEStream; @@ -54,11 +55,17 @@ public function __construct(private Client $client) {} * description: string, * selector: string, * arguments?: list, + * backendNodeID?: float, * method?: string, - * }|Action, + * }, * frameID?: string, * options?: array{ - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, * timeout?: float, * variables?: array, * }, @@ -114,11 +121,17 @@ public function act( * description: string, * selector: string, * arguments?: list, + * backendNodeID?: float, * method?: string, - * }|Action, + * }, * frameID?: string, * options?: array{ - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, * timeout?: float, * variables?: array, * }, @@ -227,7 +240,13 @@ public function end( * @param array{ * agentConfig: array{ * cua?: bool, - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|SessionExecuteParams\AgentConfig\Provider, * systemPrompt?: string, * }, * executeOptions: array{ @@ -284,7 +303,13 @@ public function execute( * @param array{ * agentConfig: array{ * cua?: bool, - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|SessionExecuteParams\AgentConfig\Provider, * systemPrompt?: string, * }, * executeOptions: array{ @@ -352,7 +377,12 @@ public function executeStream( * frameID?: string, * instruction?: string, * options?: array{ - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, * selector?: string, * timeout?: float, * }, @@ -408,7 +438,12 @@ public function extract( * frameID?: string, * instruction?: string, * options?: array{ - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, * selector?: string, * timeout?: float, * }, @@ -532,7 +567,12 @@ public function navigate( * frameID?: string, * instruction?: string, * options?: array{ - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, * selector?: string, * timeout?: float, * }, @@ -587,7 +627,12 @@ public function observe( * frameID?: string, * instruction?: string, * options?: array{ - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, * selector?: string, * timeout?: float, * }, @@ -704,12 +749,11 @@ public function observeStream( * userMetadata?: array, * }, * browserbaseSessionID?: string, - * debugDom?: bool, * domSettleTimeoutMs?: float, * experimental?: bool, * selfHeal?: bool, * systemPrompt?: string, - * verbose?: int, + * verbose?: '0'|'1'|'2'|Verbose, * waitForCaptchaSolves?: bool, * xLanguage?: 'typescript'|'python'|'playground'|SessionStartParams\XLanguage, * xSDKVersion?: string, diff --git a/src/Services/SessionsService.php b/src/Services/SessionsService.php index 49c486d..88ada27 100644 --- a/src/Services/SessionsService.php +++ b/src/Services/SessionsService.php @@ -10,7 +10,7 @@ use Stagehand\Core\Util; use Stagehand\RequestOptions; use Stagehand\ServiceContracts\SessionsContract; -use Stagehand\Sessions\Action; +use Stagehand\Sessions\ModelConfig\ModelConfigObject\Provider; use Stagehand\Sessions\SessionActParams\XLanguage; use Stagehand\Sessions\SessionActParams\XStreamResponse; use Stagehand\Sessions\SessionActResponse; @@ -26,6 +26,7 @@ use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\HTTPVersion; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\OperatingSystem; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Region; +use Stagehand\Sessions\SessionStartParams\Verbose; use Stagehand\Sessions\SessionStartResponse; use Stagehand\Sessions\StreamEvent; @@ -54,11 +55,17 @@ public function __construct(private Client $client) * description: string, * selector: string, * arguments?: list, + * backendNodeID?: float, * method?: string, - * }|Action $input Body param: Natural language instruction or Action object + * } $input Body param: Natural language instruction or Action object * @param string $frameID Body param: Target frame ID for the action * @param array{ - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, * timeout?: float, * variables?: array, * } $options Body param: @@ -71,7 +78,7 @@ public function __construct(private Client $client) */ public function act( string $id, - string|array|Action $input, + string|array $input, ?string $frameID = null, ?array $options = null, string|XLanguage|null $xLanguage = null, @@ -106,11 +113,17 @@ public function act( * description: string, * selector: string, * arguments?: list, + * backendNodeID?: float, * method?: string, - * }|Action $input Body param: Natural language instruction or Action object + * } $input Body param: Natural language instruction or Action object * @param string $frameID Body param: Target frame ID for the action * @param array{ - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, * timeout?: float, * variables?: array, * } $options Body param: @@ -125,7 +138,7 @@ public function act( */ public function actStream( string $id, - string|array|Action $input, + string|array $input, ?string $frameID = null, ?array $options = null, string|XLanguage|null $xLanguage = null, @@ -196,7 +209,13 @@ public function end( * @param string $id Path param: Unique session identifier * @param array{ * cua?: bool, - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|\Stagehand\Sessions\SessionExecuteParams\AgentConfig\Provider, * systemPrompt?: string, * } $agentConfig Body param: * @param array{ @@ -245,7 +264,13 @@ public function execute( * @param string $id Path param: Unique session identifier * @param array{ * cua?: bool, - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|\Stagehand\Sessions\SessionExecuteParams\AgentConfig\Provider, * systemPrompt?: string, * } $agentConfig Body param: * @param array{ @@ -299,7 +324,12 @@ public function executeStream( * @param string $frameID Body param: Target frame ID for the extraction * @param string $instruction Body param: Natural language instruction for what to extract * @param array{ - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, * selector?: string, * timeout?: float, * } $options Body param: @@ -349,7 +379,12 @@ public function extract( * @param string $frameID Body param: Target frame ID for the extraction * @param string $instruction Body param: Natural language instruction for what to extract * @param array{ - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, * selector?: string, * timeout?: float, * } $options Body param: @@ -455,7 +490,12 @@ public function navigate( * @param string $frameID Body param: Target frame ID for the observation * @param string $instruction Body param: Natural language instruction for what actions to find * @param array{ - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, * selector?: string, * timeout?: float, * } $options Body param: @@ -502,7 +542,12 @@ public function observe( * @param string $frameID Body param: Target frame ID for the observation * @param string $instruction Body param: Natural language instruction for what actions to find * @param array{ - * model?: string|array{modelName: string, apiKey?: string, baseURL?: string}, + * model?: string|array{ + * modelName: string, + * apiKey?: string, + * baseURL?: string, + * provider?: 'openai'|'anthropic'|'google'|'microsoft'|Provider, + * }, * selector?: string, * timeout?: float, * } $options Body param: @@ -550,7 +595,7 @@ public function observeStream( * Creates a new browser session with the specified configuration. Returns a session ID used for all subsequent operations. * * @param string $modelName Body param: Model name to use for AI operations - * @param float $actTimeoutMs Body param: Timeout in ms for act operations + * @param float $actTimeoutMs Body param: Timeout in ms for act operations (deprecated, v2 only) * @param array{ * cdpURL?: string, * launchOptions?: array{ @@ -607,13 +652,12 @@ public function observeStream( * userMetadata?: array, * } $browserbaseSessionCreateParams Body param: * @param string $browserbaseSessionID Body param: Existing Browserbase session ID to resume - * @param bool $debugDom Body param: * @param float $domSettleTimeoutMs Body param: Timeout in ms to wait for DOM to settle * @param bool $experimental Body param: * @param bool $selfHeal Body param: Enable self-healing for failed actions * @param string $systemPrompt Body param: Custom system prompt for AI operations - * @param int $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) - * @param bool $waitForCaptchaSolves Body param: + * @param '0'|'1'|'2'|Verbose $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) + * @param bool $waitForCaptchaSolves Body param: Wait for captcha solves (deprecated, v2 only) * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionStartParams\XLanguage $xLanguage Header param: Client SDK language * @param string $xSDKVersion Header param: Version of the Stagehand SDK * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent @@ -627,12 +671,11 @@ public function start( ?array $browser = null, ?array $browserbaseSessionCreateParams = null, ?string $browserbaseSessionID = null, - ?bool $debugDom = null, ?float $domSettleTimeoutMs = null, ?bool $experimental = null, ?bool $selfHeal = null, ?string $systemPrompt = null, - ?int $verbose = null, + string|Verbose|null $verbose = null, ?bool $waitForCaptchaSolves = null, string|\Stagehand\Sessions\SessionStartParams\XLanguage|null $xLanguage = null, ?string $xSDKVersion = null, @@ -647,7 +690,6 @@ public function start( 'browser' => $browser, 'browserbaseSessionCreateParams' => $browserbaseSessionCreateParams, 'browserbaseSessionID' => $browserbaseSessionID, - 'debugDom' => $debugDom, 'domSettleTimeoutMs' => $domSettleTimeoutMs, 'experimental' => $experimental, 'selfHeal' => $selfHeal, diff --git a/src/Sessions/Action.php b/src/Sessions/Action.php index 3b52526..3696c48 100644 --- a/src/Sessions/Action.php +++ b/src/Sessions/Action.php @@ -16,6 +16,7 @@ * description: string, * selector: string, * arguments?: list|null, + * backendNodeID?: float|null, * method?: string|null, * } */ @@ -44,6 +45,12 @@ final class Action implements BaseModel #[Optional(list: 'string')] public ?array $arguments; + /** + * Backend node ID for the element. + */ + #[Optional('backendNodeId')] + public ?float $backendNodeID; + /** * The method to execute (click, fill, etc.). */ @@ -80,6 +87,7 @@ public static function with( string $description, string $selector, ?array $arguments = null, + ?float $backendNodeID = null, ?string $method = null, ): self { $self = new self; @@ -88,6 +96,7 @@ public static function with( $self['selector'] = $selector; null !== $arguments && $self['arguments'] = $arguments; + null !== $backendNodeID && $self['backendNodeID'] = $backendNodeID; null !== $method && $self['method'] = $method; return $self; @@ -128,6 +137,17 @@ public function withArguments(array $arguments): self return $self; } + /** + * Backend node ID for the element. + */ + public function withBackendNodeID(float $backendNodeID): self + { + $self = clone $this; + $self['backendNodeID'] = $backendNodeID; + + return $self; + } + /** * The method to execute (click, fill, etc.). */ diff --git a/src/Sessions/ModelConfig/ModelConfigObject.php b/src/Sessions/ModelConfig/ModelConfigObject.php index f96da53..5e0eb11 100644 --- a/src/Sessions/ModelConfig/ModelConfigObject.php +++ b/src/Sessions/ModelConfig/ModelConfigObject.php @@ -8,10 +8,14 @@ use Stagehand\Core\Attributes\Required; use Stagehand\Core\Concerns\SdkModel; use Stagehand\Core\Contracts\BaseModel; +use Stagehand\Sessions\ModelConfig\ModelConfigObject\Provider; /** * @phpstan-type ModelConfigObjectShape = array{ - * modelName: string, apiKey?: string|null, baseURL?: string|null + * modelName: string, + * apiKey?: string|null, + * baseURL?: string|null, + * provider?: null|Provider|value-of, * } */ final class ModelConfigObject implements BaseModel @@ -37,6 +41,14 @@ final class ModelConfigObject implements BaseModel #[Optional] public ?string $baseURL; + /** + * AI provider for the model (or provide a baseURL endpoint instead). + * + * @var value-of|null $provider + */ + #[Optional(enum: Provider::class)] + public ?string $provider; + /** * `new ModelConfigObject()` is missing required properties by the API. * @@ -60,11 +72,14 @@ public function __construct() * Construct an instance from the required parameters. * * You must use named parameters to construct any parameters with a default value. + * + * @param Provider|value-of|null $provider */ public static function with( string $modelName, ?string $apiKey = null, - ?string $baseURL = null + ?string $baseURL = null, + Provider|string|null $provider = null, ): self { $self = new self; @@ -72,6 +87,7 @@ public static function with( null !== $apiKey && $self['apiKey'] = $apiKey; null !== $baseURL && $self['baseURL'] = $baseURL; + null !== $provider && $self['provider'] = $provider; return $self; } @@ -108,4 +124,17 @@ public function withBaseURL(string $baseURL): self return $self; } + + /** + * AI provider for the model (or provide a baseURL endpoint instead). + * + * @param Provider|value-of $provider + */ + public function withProvider(Provider|string $provider): self + { + $self = clone $this; + $self['provider'] = $provider; + + return $self; + } } diff --git a/src/Sessions/ModelConfig/ModelConfigObject/Provider.php b/src/Sessions/ModelConfig/ModelConfigObject/Provider.php new file mode 100644 index 0000000..fb1ced7 --- /dev/null +++ b/src/Sessions/ModelConfig/ModelConfigObject/Provider.php @@ -0,0 +1,19 @@ +|null, + * backendNodeID?: float|null, + * method?: string|null, + * } + */ +final class Action implements BaseModel +{ + /** @use SdkModel */ + use SdkModel; + + /** + * Human-readable description of the action. + */ + #[Required] + public string $description; + + /** + * CSS selector or XPath for the element. + */ + #[Required] + public string $selector; + + /** + * Arguments to pass to the method. + * + * @var list|null $arguments + */ + #[Optional(list: 'string')] + public ?array $arguments; + + /** + * Backend node ID for the element. + */ + #[Optional('backendNodeId')] + public ?float $backendNodeID; + + /** + * The method to execute (click, fill, etc.). + */ + #[Optional] + public ?string $method; + + /** + * `new Action()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * Action::with(description: ..., selector: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new Action)->withDescription(...)->withSelector(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param list|null $arguments + */ + public static function with( + string $description, + string $selector, + ?array $arguments = null, + ?float $backendNodeID = null, + ?string $method = null, + ): self { + $self = new self; + + $self['description'] = $description; + $self['selector'] = $selector; + + null !== $arguments && $self['arguments'] = $arguments; + null !== $backendNodeID && $self['backendNodeID'] = $backendNodeID; + null !== $method && $self['method'] = $method; + + return $self; + } + + /** + * Human-readable description of the action. + */ + public function withDescription(string $description): self + { + $self = clone $this; + $self['description'] = $description; + + return $self; + } + + /** + * CSS selector or XPath for the element. + */ + public function withSelector(string $selector): self + { + $self = clone $this; + $self['selector'] = $selector; + + return $self; + } + + /** + * Arguments to pass to the method. + * + * @param list $arguments + */ + public function withArguments(array $arguments): self + { + $self = clone $this; + $self['arguments'] = $arguments; + + return $self; + } + + /** + * Backend node ID for the element. + */ + public function withBackendNodeID(float $backendNodeID): self + { + $self = clone $this; + $self['backendNodeID'] = $backendNodeID; + + return $self; + } + + /** + * The method to execute (click, fill, etc.). + */ + public function withMethod(string $method): self + { + $self = clone $this; + $self['method'] = $method; + + return $self; + } +} diff --git a/src/Sessions/SessionExecuteParams/AgentConfig.php b/src/Sessions/SessionExecuteParams/AgentConfig.php index 60f228b..fefd2cf 100644 --- a/src/Sessions/SessionExecuteParams/AgentConfig.php +++ b/src/Sessions/SessionExecuteParams/AgentConfig.php @@ -8,12 +8,16 @@ use Stagehand\Core\Concerns\SdkModel; use Stagehand\Core\Contracts\BaseModel; use Stagehand\Sessions\ModelConfig\ModelConfigObject; +use Stagehand\Sessions\SessionExecuteParams\AgentConfig\Provider; /** * @phpstan-import-type ModelConfigShape from \Stagehand\Sessions\ModelConfig * * @phpstan-type AgentConfigShape = array{ - * cua?: bool|null, model?: ModelConfigShape|null, systemPrompt?: string|null + * cua?: bool|null, + * model?: ModelConfigShape|null, + * provider?: null|Provider|value-of, + * systemPrompt?: string|null, * } */ final class AgentConfig implements BaseModel @@ -33,6 +37,14 @@ final class AgentConfig implements BaseModel #[Optional] public string|ModelConfigObject|null $model; + /** + * AI provider for the agent (legacy, use model: openai/gpt-5-nano instead). + * + * @var value-of|null $provider + */ + #[Optional(enum: Provider::class)] + public ?string $provider; + /** * Custom system prompt for the agent. */ @@ -50,16 +62,19 @@ public function __construct() * You must use named parameters to construct any parameters with a default value. * * @param ModelConfigShape|null $model + * @param Provider|value-of|null $provider */ public static function with( ?bool $cua = null, string|ModelConfigObject|array|null $model = null, + Provider|string|null $provider = null, ?string $systemPrompt = null, ): self { $self = new self; null !== $cua && $self['cua'] = $cua; null !== $model && $self['model'] = $model; + null !== $provider && $self['provider'] = $provider; null !== $systemPrompt && $self['systemPrompt'] = $systemPrompt; return $self; @@ -89,6 +104,19 @@ public function withModel(string|ModelConfigObject|array $model): self return $self; } + /** + * AI provider for the agent (legacy, use model: openai/gpt-5-nano instead). + * + * @param Provider|value-of $provider + */ + public function withProvider(Provider|string $provider): self + { + $self = clone $this; + $self['provider'] = $provider; + + return $self; + } + /** * Custom system prompt for the agent. */ diff --git a/src/Sessions/SessionExecuteParams/AgentConfig/Provider.php b/src/Sessions/SessionExecuteParams/AgentConfig/Provider.php new file mode 100644 index 0000000..53a8864 --- /dev/null +++ b/src/Sessions/SessionExecuteParams/AgentConfig/Provider.php @@ -0,0 +1,19 @@ +, actionID?: string|null + * result: list, actionID?: string|null * } */ final class Data implements BaseModel @@ -22,8 +22,8 @@ final class Data implements BaseModel /** @use SdkModel */ use SdkModel; - /** @var list $result */ - #[Required(list: Action::class)] + /** @var list $result */ + #[Required(list: Result::class)] public array $result; /** @@ -56,7 +56,7 @@ public function __construct() * * You must use named parameters to construct any parameters with a default value. * - * @param list $result + * @param list $result */ public static function with(array $result, ?string $actionID = null): self { @@ -70,7 +70,7 @@ public static function with(array $result, ?string $actionID = null): self } /** - * @param list $result + * @param list $result */ public function withResult(array $result): self { diff --git a/src/Sessions/SessionObserveResponse/Data/Result.php b/src/Sessions/SessionObserveResponse/Data/Result.php new file mode 100644 index 0000000..1bc17e4 --- /dev/null +++ b/src/Sessions/SessionObserveResponse/Data/Result.php @@ -0,0 +1,161 @@ +|null, + * backendNodeID?: float|null, + * method?: string|null, + * } + */ +final class Result implements BaseModel +{ + /** @use SdkModel */ + use SdkModel; + + /** + * Human-readable description of the action. + */ + #[Required] + public string $description; + + /** + * CSS selector or XPath for the element. + */ + #[Required] + public string $selector; + + /** + * Arguments to pass to the method. + * + * @var list|null $arguments + */ + #[Optional(list: 'string')] + public ?array $arguments; + + /** + * Backend node ID for the element. + */ + #[Optional('backendNodeId')] + public ?float $backendNodeID; + + /** + * The method to execute (click, fill, etc.). + */ + #[Optional] + public ?string $method; + + /** + * `new Result()` is missing required properties by the API. + * + * To enforce required parameters use + * ``` + * Result::with(description: ..., selector: ...) + * ``` + * + * Otherwise ensure the following setters are called + * + * ``` + * (new Result)->withDescription(...)->withSelector(...) + * ``` + */ + public function __construct() + { + $this->initialize(); + } + + /** + * Construct an instance from the required parameters. + * + * You must use named parameters to construct any parameters with a default value. + * + * @param list|null $arguments + */ + public static function with( + string $description, + string $selector, + ?array $arguments = null, + ?float $backendNodeID = null, + ?string $method = null, + ): self { + $self = new self; + + $self['description'] = $description; + $self['selector'] = $selector; + + null !== $arguments && $self['arguments'] = $arguments; + null !== $backendNodeID && $self['backendNodeID'] = $backendNodeID; + null !== $method && $self['method'] = $method; + + return $self; + } + + /** + * Human-readable description of the action. + */ + public function withDescription(string $description): self + { + $self = clone $this; + $self['description'] = $description; + + return $self; + } + + /** + * CSS selector or XPath for the element. + */ + public function withSelector(string $selector): self + { + $self = clone $this; + $self['selector'] = $selector; + + return $self; + } + + /** + * Arguments to pass to the method. + * + * @param list $arguments + */ + public function withArguments(array $arguments): self + { + $self = clone $this; + $self['arguments'] = $arguments; + + return $self; + } + + /** + * Backend node ID for the element. + */ + public function withBackendNodeID(float $backendNodeID): self + { + $self = clone $this; + $self['backendNodeID'] = $backendNodeID; + + return $self; + } + + /** + * The method to execute (click, fill, etc.). + */ + public function withMethod(string $method): self + { + $self = clone $this; + $self['method'] = $method; + + return $self; + } +} diff --git a/src/Sessions/SessionStartParams.php b/src/Sessions/SessionStartParams.php index f6a22e9..7bf8d7e 100644 --- a/src/Sessions/SessionStartParams.php +++ b/src/Sessions/SessionStartParams.php @@ -11,6 +11,7 @@ use Stagehand\Core\Contracts\BaseModel; use Stagehand\Sessions\SessionStartParams\Browser; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams; +use Stagehand\Sessions\SessionStartParams\Verbose; use Stagehand\Sessions\SessionStartParams\XLanguage; use Stagehand\Sessions\SessionStartParams\XStreamResponse; @@ -28,12 +29,11 @@ * browser?: null|Browser|BrowserShape, * browserbaseSessionCreateParams?: null|BrowserbaseSessionCreateParams|BrowserbaseSessionCreateParamsShape, * browserbaseSessionID?: string|null, - * debugDom?: bool|null, * domSettleTimeoutMs?: float|null, * experimental?: bool|null, * selfHeal?: bool|null, * systemPrompt?: string|null, - * verbose?: int|null, + * verbose?: null|Verbose|value-of, * waitForCaptchaSolves?: bool|null, * xLanguage?: null|XLanguage|value-of, * xSDKVersion?: string|null, @@ -54,7 +54,7 @@ final class SessionStartParams implements BaseModel public string $modelName; /** - * Timeout in ms for act operations. + * Timeout in ms for act operations (deprecated, v2 only). */ #[Optional] public ?float $actTimeoutMs; @@ -71,9 +71,6 @@ final class SessionStartParams implements BaseModel #[Optional] public ?string $browserbaseSessionID; - #[Optional] - public ?bool $debugDom; - /** * Timeout in ms to wait for DOM to settle. */ @@ -97,10 +94,15 @@ final class SessionStartParams implements BaseModel /** * Logging verbosity level (0=quiet, 1=normal, 2=debug). + * + * @var value-of|null $verbose */ - #[Optional] - public ?int $verbose; + #[Optional(enum: Verbose::class)] + public ?string $verbose; + /** + * Wait for captcha solves (deprecated, v2 only). + */ #[Optional] public ?bool $waitForCaptchaSolves; @@ -158,6 +160,7 @@ public function __construct() * * @param Browser|BrowserShape|null $browser * @param BrowserbaseSessionCreateParams|BrowserbaseSessionCreateParamsShape|null $browserbaseSessionCreateParams + * @param Verbose|value-of|null $verbose * @param XLanguage|value-of|null $xLanguage * @param XStreamResponse|value-of|null $xStreamResponse */ @@ -167,12 +170,11 @@ public static function with( Browser|array|null $browser = null, BrowserbaseSessionCreateParams|array|null $browserbaseSessionCreateParams = null, ?string $browserbaseSessionID = null, - ?bool $debugDom = null, ?float $domSettleTimeoutMs = null, ?bool $experimental = null, ?bool $selfHeal = null, ?string $systemPrompt = null, - ?int $verbose = null, + Verbose|string|null $verbose = null, ?bool $waitForCaptchaSolves = null, XLanguage|string|null $xLanguage = null, ?string $xSDKVersion = null, @@ -187,7 +189,6 @@ public static function with( null !== $browser && $self['browser'] = $browser; null !== $browserbaseSessionCreateParams && $self['browserbaseSessionCreateParams'] = $browserbaseSessionCreateParams; null !== $browserbaseSessionID && $self['browserbaseSessionID'] = $browserbaseSessionID; - null !== $debugDom && $self['debugDom'] = $debugDom; null !== $domSettleTimeoutMs && $self['domSettleTimeoutMs'] = $domSettleTimeoutMs; null !== $experimental && $self['experimental'] = $experimental; null !== $selfHeal && $self['selfHeal'] = $selfHeal; @@ -214,7 +215,7 @@ public function withModelName(string $modelName): self } /** - * Timeout in ms for act operations. + * Timeout in ms for act operations (deprecated, v2 only). */ public function withActTimeoutMs(float $actTimeoutMs): self { @@ -258,14 +259,6 @@ public function withBrowserbaseSessionID(string $browserbaseSessionID): self return $self; } - public function withDebugDom(bool $debugDom): self - { - $self = clone $this; - $self['debugDom'] = $debugDom; - - return $self; - } - /** * Timeout in ms to wait for DOM to settle. */ @@ -309,8 +302,10 @@ public function withSystemPrompt(string $systemPrompt): self /** * Logging verbosity level (0=quiet, 1=normal, 2=debug). + * + * @param Verbose|value-of $verbose */ - public function withVerbose(int $verbose): self + public function withVerbose(Verbose|string $verbose): self { $self = clone $this; $self['verbose'] = $verbose; @@ -318,6 +313,9 @@ public function withVerbose(int $verbose): self return $self; } + /** + * Wait for captcha solves (deprecated, v2 only). + */ public function withWaitForCaptchaSolves(bool $waitForCaptchaSolves): self { $self = clone $this; diff --git a/src/Sessions/SessionStartParams/Verbose.php b/src/Sessions/SessionStartParams/Verbose.php new file mode 100644 index 0000000..0831dce --- /dev/null +++ b/src/Sessions/SessionStartParams/Verbose.php @@ -0,0 +1,17 @@ +withAvailable(...)->withConnectURL(...)->withSessionID(...) + * (new Data)->withAvailable(...)->withSessionID(...) * ``` */ public function __construct() @@ -59,15 +60,16 @@ public function __construct() */ public static function with( bool $available, - string $connectURL, - string $sessionID + string $sessionID, + ?string $cdpURL = null ): self { $self = new self; $self['available'] = $available; - $self['connectURL'] = $connectURL; $self['sessionID'] = $sessionID; + null !== $cdpURL && $self['cdpURL'] = $cdpURL; + return $self; } @@ -80,23 +82,23 @@ public function withAvailable(bool $available): self } /** - * CDP WebSocket URL for connecting to the Browserbase cloud browser. + * Unique Browserbase session identifier. */ - public function withConnectURL(string $connectURL): self + public function withSessionID(string $sessionID): self { $self = clone $this; - $self['connectURL'] = $connectURL; + $self['sessionID'] = $sessionID; return $self; } /** - * Unique Browserbase session identifier. + * CDP WebSocket URL for connecting to the Browserbase cloud browser (present when available). */ - public function withSessionID(string $sessionID): self + public function withCdpURL(?string $cdpURL): self { $self = clone $this; - $self['sessionID'] = $sessionID; + $self['cdpURL'] = $cdpURL; return $self; } diff --git a/src/Sessions/StreamEvent.php b/src/Sessions/StreamEvent.php index 14261ce..f75321a 100644 --- a/src/Sessions/StreamEvent.php +++ b/src/Sessions/StreamEvent.php @@ -12,7 +12,7 @@ use Stagehand\Sessions\StreamEvent\Type; /** - * Server-Sent Event emitted during streaming responses. Events are sent as `data: \n\n`. + * Server-Sent Event emitted during streaming responses. Events are sent as `data: \n\n`. Key order: data (with status first), type, id. * * @phpstan-import-type DataShape from \Stagehand\Sessions\StreamEvent\Data * diff --git a/tests/Services/SessionsTest.php b/tests/Services/SessionsTest.php index 414c211..b86aa96 100644 --- a/tests/Services/SessionsTest.php +++ b/tests/Services/SessionsTest.php @@ -126,6 +126,7 @@ public function testExecuteWithOptionalParams(): void agentConfig: [ 'cua' => true, 'model' => 'openai/gpt-5-nano', + 'provider' => 'openai', 'systemPrompt' => 'systemPrompt', ], executeOptions: [ @@ -237,7 +238,7 @@ public function testStartWithOptionalParams(): void $result = $this->client->sessions->start( modelName: 'gpt-4o', - actTimeoutMs: 30000, + actTimeoutMs: 0, browser: [ 'cdpURL' => 'ws://localhost:9222', 'launchOptions' => [ @@ -300,12 +301,11 @@ public function testStartWithOptionalParams(): void 'userMetadata' => ['foo' => 'bar'], ], browserbaseSessionID: 'browserbaseSessionID', - debugDom: true, domSettleTimeoutMs: 5000, experimental: true, selfHeal: true, systemPrompt: 'systemPrompt', - verbose: 1, + verbose: '1', waitForCaptchaSolves: true, xLanguage: 'typescript', xSDKVersion: '3.0.6', From 1a0904d4498d41422c6a341ffdbcefcb9f5710c1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 20 Dec 2025 04:58:39 +0000 Subject: [PATCH 21/29] docs: add more examples --- README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/README.md b/README.md index f15bb6c..a345c11 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,33 @@ and named parameters to initialize value objects. However, builders are also provided `(new Action)->withDescription('Click the submit button')`. +### Streaming + +We provide support for streaming responses using Server-Sent Events (SSE). + +```php +sessions->actStream( + '00000000-your-session-id-000000000000', + input: 'click the first link on the page', +); + +foreach ($stream as $response) { + var_dump($response); +} +``` + ### Handling errors When the library is unable to connect to the API, or if the API returns a non-success status code (i.e., 4xx or 5xx response), a subclass of `Stagehand\Core\Exceptions\APIException` will be thrown: From 3d7bdf5f97754c73ae6eb48ea8349f2c8ffc66a8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 22 Dec 2025 21:50:59 +0000 Subject: [PATCH 22/29] feat: [STG-1053] [server] Use fastify-zod-openapi + zod v4 for openapi generation --- .stats.yml | 4 ++-- src/ServiceContracts/SessionsContract.php | 5 ++--- src/Services/SessionsRawService.php | 3 +-- src/Services/SessionsService.php | 5 ++--- src/Sessions/SessionStartParams.php | 16 +++++----------- src/Sessions/SessionStartParams/Verbose.php | 17 ----------------- tests/Services/SessionsTest.php | 2 +- 7 files changed, 13 insertions(+), 39 deletions(-) delete mode 100644 src/Sessions/SessionStartParams/Verbose.php diff --git a/.stats.yml b/.stats.yml index d90df61..2c7a523 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-4fb17cafc413ae3d575e3268602b01d2d0e9ebeb734a41b6086b3353ff0d2523.yml -openapi_spec_hash: 8d48d8564849246f6f14d900c6c5f60c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-ed52466945f2f8dfd3814a29e948d7bf30af7b76a7a7689079c03b8baf64e26f.yml +openapi_spec_hash: 5d57aaf2362b0d882372dbf76477ba23 config_hash: 5c69fb596588b8ace08203858518c149 diff --git a/src/ServiceContracts/SessionsContract.php b/src/ServiceContracts/SessionsContract.php index 262f72c..482bca1 100644 --- a/src/ServiceContracts/SessionsContract.php +++ b/src/ServiceContracts/SessionsContract.php @@ -23,7 +23,6 @@ use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\HTTPVersion; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\OperatingSystem; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Region; -use Stagehand\Sessions\SessionStartParams\Verbose; use Stagehand\Sessions\SessionStartResponse; use Stagehand\Sessions\StreamEvent; @@ -456,7 +455,7 @@ public function observeStream( * @param bool $experimental Body param: * @param bool $selfHeal Body param: Enable self-healing for failed actions * @param string $systemPrompt Body param: Custom system prompt for AI operations - * @param '0'|'1'|'2'|Verbose $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) + * @param float $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) * @param bool $waitForCaptchaSolves Body param: Wait for captcha solves (deprecated, v2 only) * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionStartParams\XLanguage $xLanguage Header param: Client SDK language * @param string $xSDKVersion Header param: Version of the Stagehand SDK @@ -475,7 +474,7 @@ public function start( ?bool $experimental = null, ?bool $selfHeal = null, ?string $systemPrompt = null, - string|Verbose|null $verbose = null, + ?float $verbose = null, ?bool $waitForCaptchaSolves = null, string|\Stagehand\Sessions\SessionStartParams\XLanguage|null $xLanguage = null, ?string $xSDKVersion = null, diff --git a/src/Services/SessionsRawService.php b/src/Services/SessionsRawService.php index a56604d..1561beb 100644 --- a/src/Services/SessionsRawService.php +++ b/src/Services/SessionsRawService.php @@ -31,7 +31,6 @@ use Stagehand\Sessions\SessionStartParams\Browser\Type; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\HTTPVersion; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Region; -use Stagehand\Sessions\SessionStartParams\Verbose; use Stagehand\Sessions\SessionStartResponse; use Stagehand\Sessions\StreamEvent; use Stagehand\SSEStream; @@ -753,7 +752,7 @@ public function observeStream( * experimental?: bool, * selfHeal?: bool, * systemPrompt?: string, - * verbose?: '0'|'1'|'2'|Verbose, + * verbose?: float, * waitForCaptchaSolves?: bool, * xLanguage?: 'typescript'|'python'|'playground'|SessionStartParams\XLanguage, * xSDKVersion?: string, diff --git a/src/Services/SessionsService.php b/src/Services/SessionsService.php index 88ada27..df39515 100644 --- a/src/Services/SessionsService.php +++ b/src/Services/SessionsService.php @@ -26,7 +26,6 @@ use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\HTTPVersion; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\BrowserSettings\Fingerprint\OperatingSystem; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams\Region; -use Stagehand\Sessions\SessionStartParams\Verbose; use Stagehand\Sessions\SessionStartResponse; use Stagehand\Sessions\StreamEvent; @@ -656,7 +655,7 @@ public function observeStream( * @param bool $experimental Body param: * @param bool $selfHeal Body param: Enable self-healing for failed actions * @param string $systemPrompt Body param: Custom system prompt for AI operations - * @param '0'|'1'|'2'|Verbose $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) + * @param float $verbose Body param: Logging verbosity level (0=quiet, 1=normal, 2=debug) * @param bool $waitForCaptchaSolves Body param: Wait for captcha solves (deprecated, v2 only) * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionStartParams\XLanguage $xLanguage Header param: Client SDK language * @param string $xSDKVersion Header param: Version of the Stagehand SDK @@ -675,7 +674,7 @@ public function start( ?bool $experimental = null, ?bool $selfHeal = null, ?string $systemPrompt = null, - string|Verbose|null $verbose = null, + ?float $verbose = null, ?bool $waitForCaptchaSolves = null, string|\Stagehand\Sessions\SessionStartParams\XLanguage|null $xLanguage = null, ?string $xSDKVersion = null, diff --git a/src/Sessions/SessionStartParams.php b/src/Sessions/SessionStartParams.php index 7bf8d7e..0950eea 100644 --- a/src/Sessions/SessionStartParams.php +++ b/src/Sessions/SessionStartParams.php @@ -11,7 +11,6 @@ use Stagehand\Core\Contracts\BaseModel; use Stagehand\Sessions\SessionStartParams\Browser; use Stagehand\Sessions\SessionStartParams\BrowserbaseSessionCreateParams; -use Stagehand\Sessions\SessionStartParams\Verbose; use Stagehand\Sessions\SessionStartParams\XLanguage; use Stagehand\Sessions\SessionStartParams\XStreamResponse; @@ -33,7 +32,7 @@ * experimental?: bool|null, * selfHeal?: bool|null, * systemPrompt?: string|null, - * verbose?: null|Verbose|value-of, + * verbose?: float|null, * waitForCaptchaSolves?: bool|null, * xLanguage?: null|XLanguage|value-of, * xSDKVersion?: string|null, @@ -94,11 +93,9 @@ final class SessionStartParams implements BaseModel /** * Logging verbosity level (0=quiet, 1=normal, 2=debug). - * - * @var value-of|null $verbose */ - #[Optional(enum: Verbose::class)] - public ?string $verbose; + #[Optional] + public ?float $verbose; /** * Wait for captcha solves (deprecated, v2 only). @@ -160,7 +157,6 @@ public function __construct() * * @param Browser|BrowserShape|null $browser * @param BrowserbaseSessionCreateParams|BrowserbaseSessionCreateParamsShape|null $browserbaseSessionCreateParams - * @param Verbose|value-of|null $verbose * @param XLanguage|value-of|null $xLanguage * @param XStreamResponse|value-of|null $xStreamResponse */ @@ -174,7 +170,7 @@ public static function with( ?bool $experimental = null, ?bool $selfHeal = null, ?string $systemPrompt = null, - Verbose|string|null $verbose = null, + ?float $verbose = null, ?bool $waitForCaptchaSolves = null, XLanguage|string|null $xLanguage = null, ?string $xSDKVersion = null, @@ -302,10 +298,8 @@ public function withSystemPrompt(string $systemPrompt): self /** * Logging verbosity level (0=quiet, 1=normal, 2=debug). - * - * @param Verbose|value-of $verbose */ - public function withVerbose(Verbose|string $verbose): self + public function withVerbose(float $verbose): self { $self = clone $this; $self['verbose'] = $verbose; diff --git a/src/Sessions/SessionStartParams/Verbose.php b/src/Sessions/SessionStartParams/Verbose.php deleted file mode 100644 index 0831dce..0000000 --- a/src/Sessions/SessionStartParams/Verbose.php +++ /dev/null @@ -1,17 +0,0 @@ - Date: Tue, 23 Dec 2025 19:54:22 +0000 Subject: [PATCH 23/29] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 2c7a523..21604fb 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-ed52466945f2f8dfd3814a29e948d7bf30af7b76a7a7689079c03b8baf64e26f.yml openapi_spec_hash: 5d57aaf2362b0d882372dbf76477ba23 -config_hash: 5c69fb596588b8ace08203858518c149 +config_hash: 6b5d2b7e13aea77b1fd038e5eb8c0662 From 29d21df5c0ef4e18fba4b55a8937d9a4f33eca50 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 23 Dec 2025 20:07:56 +0000 Subject: [PATCH 24/29] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 21604fb..5a89fb7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-ed52466945f2f8dfd3814a29e948d7bf30af7b76a7a7689079c03b8baf64e26f.yml openapi_spec_hash: 5d57aaf2362b0d882372dbf76477ba23 -config_hash: 6b5d2b7e13aea77b1fd038e5eb8c0662 +config_hash: 989ddfee371586e9156b4d484ec0a6cc From 9cdfcfd1bcbdce9a8c9320b5efac239e5ee8cf6c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 5 Jan 2026 21:38:34 +0000 Subject: [PATCH 25/29] feat(api): manual updates --- .stats.yml | 2 +- LICENSE | 2 +- src/Client.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 5a89fb7..3a11178 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-ed52466945f2f8dfd3814a29e948d7bf30af7b76a7a7689079c03b8baf64e26f.yml openapi_spec_hash: 5d57aaf2362b0d882372dbf76477ba23 -config_hash: 989ddfee371586e9156b4d484ec0a6cc +config_hash: 8ec9eaf59304f664cf79f73de1488671 diff --git a/LICENSE b/LICENSE index 6b24314..d15d021 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2025 Stagehand + Copyright 2026 Stagehand Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/Client.php b/src/Client.php index 2629b4d..e24fda7 100644 --- a/src/Client.php +++ b/src/Client.php @@ -35,7 +35,7 @@ public function __construct( $baseUrl ??= getenv( 'STAGEHAND_BASE_URL' - ) ?: 'https://api.stagehand.browserbase.com/v1'; + ) ?: 'https://api.stagehand.browserbase.com'; $options = RequestOptions::with( uriFactory: Psr17FactoryDiscovery::findUriFactory(), From d4e06b08d70f71527f92da3cfa46179884775480 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 6 Jan 2026 03:46:40 +0000 Subject: [PATCH 26/29] codegen metadata --- .stats.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 3a11178..1915416 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-ed52466945f2f8dfd3814a29e948d7bf30af7b76a7a7689079c03b8baf64e26f.yml -openapi_spec_hash: 5d57aaf2362b0d882372dbf76477ba23 -config_hash: 8ec9eaf59304f664cf79f73de1488671 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-2c6c017cc9ca1fcfe7b3902edfa64fb0420bdb46b1740c7c862e81e2132d4f7c.yml +openapi_spec_hash: 220daf7e8f5897909a6c10e3385386e3 +config_hash: 1f709f8775e13029dc60064ef3a94355 From 7405f84d11aec0e4d031da5cce447fe841c77ec3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 6 Jan 2026 19:34:43 +0000 Subject: [PATCH 27/29] feat: Added optional param to force empty object --- .stats.yml | 4 ++-- src/ServiceContracts/SessionsContract.php | 12 +++++++----- src/ServiceContracts/SessionsRawContract.php | 2 +- src/Services/SessionsRawService.php | 20 +++++++++++++------- src/Services/SessionsService.php | 13 ++++++++----- src/Sessions/SessionEndParams.php | 14 ++++++++++++++ 6 files changed, 45 insertions(+), 20 deletions(-) diff --git a/.stats.yml b/.stats.yml index 1915416..f4f95e8 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-2c6c017cc9ca1fcfe7b3902edfa64fb0420bdb46b1740c7c862e81e2132d4f7c.yml -openapi_spec_hash: 220daf7e8f5897909a6c10e3385386e3 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-39cd9547d16412cf0568f6ce2ad8d43805dffe65bde830beeff630b903ae3b38.yml +openapi_spec_hash: 9cd7c9fefa686f9711392782d948470f config_hash: 1f709f8775e13029dc60064ef3a94355 diff --git a/src/ServiceContracts/SessionsContract.php b/src/ServiceContracts/SessionsContract.php index 482bca1..aa6235e 100644 --- a/src/ServiceContracts/SessionsContract.php +++ b/src/ServiceContracts/SessionsContract.php @@ -115,16 +115,18 @@ public function actStream( /** * @api * - * @param string $id Unique session identifier - * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionEndParams\XLanguage $xLanguage Client SDK language - * @param string $xSDKVersion Version of the Stagehand SDK - * @param string|\DateTimeInterface $xSentAt ISO timestamp when request was sent - * @param 'true'|'false'|\Stagehand\Sessions\SessionEndParams\XStreamResponse $xStreamResponse Whether to stream the response via SSE + * @param string $id Path param: Unique session identifier + * @param mixed $_forceBody Body param: + * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionEndParams\XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|\Stagehand\Sessions\SessionEndParams\XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE * * @throws APIException */ public function end( string $id, + mixed $_forceBody = null, string|\Stagehand\Sessions\SessionEndParams\XLanguage|null $xLanguage = null, ?string $xSDKVersion = null, string|\DateTimeInterface|null $xSentAt = null, diff --git a/src/ServiceContracts/SessionsRawContract.php b/src/ServiceContracts/SessionsRawContract.php index 3051c3f..5b392d6 100644 --- a/src/ServiceContracts/SessionsRawContract.php +++ b/src/ServiceContracts/SessionsRawContract.php @@ -61,7 +61,7 @@ public function actStream( /** * @api * - * @param string $id Unique session identifier + * @param string $id Path param: Unique session identifier * @param array|SessionEndParams $params * * @return BaseResponse diff --git a/src/Services/SessionsRawService.php b/src/Services/SessionsRawService.php index 1561beb..dc8437d 100644 --- a/src/Services/SessionsRawService.php +++ b/src/Services/SessionsRawService.php @@ -190,8 +190,9 @@ public function actStream( * * Terminates the browser session and releases all associated resources. * - * @param string $id Unique session identifier + * @param string $id Path param: Unique session identifier * @param array{ + * _forceBody?: mixed, * xLanguage?: 'typescript'|'python'|'playground'|XLanguage, * xSDKVersion?: string, * xSentAt?: string|\DateTimeInterface, @@ -211,19 +212,24 @@ public function end( $params, $requestOptions, ); + $header_params = [ + 'xLanguage' => 'x-language', + 'xSDKVersion' => 'x-sdk-version', + 'xSentAt' => 'x-sent-at', + 'xStreamResponse' => 'x-stream-response', + ]; // @phpstan-ignore-next-line return.type return $this->client->request( method: 'post', path: ['v1/sessions/%1$s/end', $id], headers: Util::array_transform_keys( + array_intersect_key($parsed, array_flip(array_keys($header_params))), + $header_params, + ), + body: (object) array_diff_key( $parsed, - [ - 'xLanguage' => 'x-language', - 'xSDKVersion' => 'x-sdk-version', - 'xSentAt' => 'x-sent-at', - 'xStreamResponse' => 'x-stream-response', - ], + array_flip(array_keys($header_params)) ), options: $options, convert: SessionEndResponse::class, diff --git a/src/Services/SessionsService.php b/src/Services/SessionsService.php index df39515..3128614 100644 --- a/src/Services/SessionsService.php +++ b/src/Services/SessionsService.php @@ -169,16 +169,18 @@ public function actStream( * * Terminates the browser session and releases all associated resources. * - * @param string $id Unique session identifier - * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionEndParams\XLanguage $xLanguage Client SDK language - * @param string $xSDKVersion Version of the Stagehand SDK - * @param string|\DateTimeInterface $xSentAt ISO timestamp when request was sent - * @param 'true'|'false'|\Stagehand\Sessions\SessionEndParams\XStreamResponse $xStreamResponse Whether to stream the response via SSE + * @param string $id Path param: Unique session identifier + * @param mixed $_forceBody Body param: + * @param 'typescript'|'python'|'playground'|\Stagehand\Sessions\SessionEndParams\XLanguage $xLanguage Header param: Client SDK language + * @param string $xSDKVersion Header param: Version of the Stagehand SDK + * @param string|\DateTimeInterface $xSentAt Header param: ISO timestamp when request was sent + * @param 'true'|'false'|\Stagehand\Sessions\SessionEndParams\XStreamResponse $xStreamResponse Header param: Whether to stream the response via SSE * * @throws APIException */ public function end( string $id, + mixed $_forceBody = null, string|\Stagehand\Sessions\SessionEndParams\XLanguage|null $xLanguage = null, ?string $xSDKVersion = null, string|\DateTimeInterface|null $xSentAt = null, @@ -187,6 +189,7 @@ public function end( ): SessionEndResponse { $params = Util::removeNulls( [ + '_forceBody' => $_forceBody, 'xLanguage' => $xLanguage, 'xSDKVersion' => $xSDKVersion, 'xSentAt' => $xSentAt, diff --git a/src/Sessions/SessionEndParams.php b/src/Sessions/SessionEndParams.php index 1528ec0..56ba309 100644 --- a/src/Sessions/SessionEndParams.php +++ b/src/Sessions/SessionEndParams.php @@ -17,6 +17,7 @@ * @see Stagehand\Services\SessionsService::end() * * @phpstan-type SessionEndParamsShape = array{ + * _forceBody?: mixed, * xLanguage?: null|XLanguage|value-of, * xSDKVersion?: string|null, * xSentAt?: \DateTimeInterface|null, @@ -29,6 +30,9 @@ final class SessionEndParams implements BaseModel use SdkModel; use SdkParams; + #[Optional] + public mixed $_forceBody; + /** * Client SDK language. * @@ -71,6 +75,7 @@ public function __construct() * @param XStreamResponse|value-of|null $xStreamResponse */ public static function with( + mixed $_forceBody = null, XLanguage|string|null $xLanguage = null, ?string $xSDKVersion = null, ?\DateTimeInterface $xSentAt = null, @@ -78,6 +83,7 @@ public static function with( ): self { $self = new self; + null !== $_forceBody && $self['_forceBody'] = $_forceBody; null !== $xLanguage && $self['xLanguage'] = $xLanguage; null !== $xSDKVersion && $self['xSDKVersion'] = $xSDKVersion; null !== $xSentAt && $self['xSentAt'] = $xSentAt; @@ -86,6 +92,14 @@ public static function with( return $self; } + public function withForceBody(mixed $_forceBody): self + { + $self = clone $this; + $self['_forceBody'] = $_forceBody; + + return $self; + } + /** * Client SDK language. * From ccced14ea53cfa8120ab9226eb84465703eb7f63 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 05:02:06 +0000 Subject: [PATCH 28/29] chore(internal): refactor auth by moving concern from base client into client --- src/Client.php | 42 ++++++++++++++++++++ src/Core/BaseClient.php | 51 ++++++------------------- src/Core/Concerns/SdkPage.php | 4 +- src/Core/Contracts/BasePage.php | 4 +- src/Core/Implementation/RawResponse.php | 6 +-- src/RequestOptions.php | 8 ++-- 6 files changed, 66 insertions(+), 49 deletions(-) diff --git a/src/Client.php b/src/Client.php index e24fda7..6358a75 100644 --- a/src/Client.php +++ b/src/Client.php @@ -10,6 +10,10 @@ use Stagehand\Core\Util; use Stagehand\Services\SessionsService; +/** + * @phpstan-import-type NormalizedRequest from \Stagehand\Core\BaseClient + * @phpstan-import-type RequestOpts from \Stagehand\RequestOptions + */ class Client extends BaseClient { public string $browserbaseAPIKey; @@ -63,6 +67,16 @@ public function __construct( $this->sessions = new SessionsService($this); } + /** @return array */ + protected function authHeaders(): array + { + return [ + ...$this->bbAPIKeyAuth(), + ...$this->bbProjectIDAuth(), + ...$this->llmModelAPIKeyAuth(), + ]; + } + /** @return array */ protected function bbAPIKeyAuth(): array { @@ -84,4 +98,32 @@ protected function llmModelAPIKeyAuth(): array { return $this->modelAPIKey ? ['x-model-api-key' => $this->modelAPIKey] : []; } + + /** + * @internal + * + * @param string|list $path + * @param array $query + * @param array|null> $headers + * @param RequestOpts|null $opts + * + * @return array{NormalizedRequest, RequestOptions} + */ + protected function buildRequest( + string $method, + string|array $path, + array $query, + array $headers, + mixed $body, + RequestOptions|array|null $opts, + ): array { + return parent::buildRequest( + method: $method, + path: $path, + query: $query, + headers: [...$this->authHeaders(), ...$headers], + body: $body, + opts: $opts, + ); + } } diff --git a/src/Core/BaseClient.php b/src/Core/BaseClient.php index 36371fb..eb7c6dd 100644 --- a/src/Core/BaseClient.php +++ b/src/Core/BaseClient.php @@ -5,12 +5,8 @@ namespace Stagehand\Core; use Psr\Http\Client\ClientExceptionInterface; -use Psr\Http\Client\ClientInterface; -use Psr\Http\Message\RequestFactoryInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\StreamFactoryInterface; -use Psr\Http\Message\UriFactoryInterface; use Psr\Http\Message\UriInterface; use Stagehand\Core\Contracts\BasePage; use Stagehand\Core\Contracts\BaseResponse; @@ -23,7 +19,9 @@ use Stagehand\RequestOptions; /** - * @phpstan-type normalized_request = array{ + * @phpstan-import-type RequestOpts from \Stagehand\RequestOptions + * + * @phpstan-type NormalizedRequest = array{ * method: string, * path: string, * query: array, @@ -80,6 +78,7 @@ public function request( $request = $opts->requestFactory->createRequest($method, uri: $uri); $request = Util::withSetHeaders($request, headers: $headers); + $request = $this->transformRequest($request); // @phpstan-ignore-next-line argument.type $rsp = $this->sendRequest($opts, req: $request, data: $data, redirectCount: 0, retryCount: 0); @@ -88,25 +87,6 @@ public function request( return new RawResponse(client: $this, request: $request, response: $rsp, options: $opts, requestInfo: $req, unwrap: $unwrap, stream: $stream, page: $page, convert: $convert ?? 'null'); } - /** @return array */ - protected function authHeaders(): array - { - return [ - ...$this->bbAPIKeyAuth(), - ...$this->bbProjectIDAuth(), - ...$this->llmModelAPIKeyAuth(), - ]; - } - - /** @return array */ - abstract protected function bbAPIKeyAuth(): array; - - /** @return array */ - abstract protected function bbProjectIDAuth(): array; - - /** @return array */ - abstract protected function llmModelAPIKeyAuth(): array; - /** * @internal */ @@ -123,21 +103,9 @@ protected function generateIdempotencyKey(): string * @param string|list $path * @param array $query * @param array|null> $headers - * @param array{ - * timeout?: float|null, - * maxRetries?: int|null, - * initialRetryDelay?: float|null, - * maxRetryDelay?: float|null, - * extraHeaders?: array|null>|null, - * extraQueryParams?: array|null, - * extraBodyParams?: mixed, - * transporter?: ClientInterface|null, - * uriFactory?: UriFactoryInterface|null, - * streamFactory?: StreamFactoryInterface|null, - * requestFactory?: RequestFactoryInterface|null, - * }|null $opts + * @param RequestOpts|null $opts * - * @return array{normalized_request, RequestOptions} + * @return array{NormalizedRequest, RequestOptions} */ protected function buildRequest( string $method, @@ -164,7 +132,6 @@ protected function buildRequest( /** @var array|null> $mergedHeaders */ $mergedHeaders = [ ...$this->headers, - ...$this->authHeaders(), ...$headers, ...($options->extraHeaders ?? []), ...$idempotencyHeaders, @@ -175,6 +142,12 @@ protected function buildRequest( return [$req, $options]; } + protected function transformRequest( + RequestInterface $request + ): RequestInterface { + return $request; + } + /** * @internal */ diff --git a/src/Core/Concerns/SdkPage.php b/src/Core/Concerns/SdkPage.php index 19bd4f2..9bdf711 100644 --- a/src/Core/Concerns/SdkPage.php +++ b/src/Core/Concerns/SdkPage.php @@ -12,6 +12,8 @@ use Stagehand\RequestOptions; /** + * @phpstan-import-type NormalizedRequest from \Stagehand\Core\BaseClient + * * @internal * * @template Item @@ -94,7 +96,7 @@ public function pagingEachItem(): \Generator /** * @internal * - * @return array{normalized_request, RequestOptions} + * @return array{NormalizedRequest, RequestOptions} */ abstract protected function nextRequest(): ?array; } diff --git a/src/Core/Contracts/BasePage.php b/src/Core/Contracts/BasePage.php index 2afa086..13e1301 100644 --- a/src/Core/Contracts/BasePage.php +++ b/src/Core/Contracts/BasePage.php @@ -5,9 +5,9 @@ namespace Stagehand\Core\Contracts; /** - * @internal + * @phpstan-import-type NormalizedRequest from \Stagehand\Core\BaseClient * - * @phpstan-import-type normalized_request from \Stagehand\Core\BaseClient + * @internal * * @template Item * diff --git a/src/Core/Implementation/RawResponse.php b/src/Core/Implementation/RawResponse.php index d54840d..aaedbc2 100644 --- a/src/Core/Implementation/RawResponse.php +++ b/src/Core/Implementation/RawResponse.php @@ -14,13 +14,13 @@ use Stagehand\RequestOptions; /** + * @phpstan-import-type NormalizedRequest from \Stagehand\Core\BaseClient + * * @internal * * @template R * * @implements BaseResponse - * - * @phpstan-import-type normalized_request from \Stagehand\Core\BaseClient */ class RawResponse implements BaseResponse { @@ -35,7 +35,7 @@ class RawResponse implements BaseResponse private bool $coerced = false; /** - * @param normalized_request $requestInfo + * @param NormalizedRequest $requestInfo * @param list|string|int|null $unwrap */ public function __construct( diff --git a/src/RequestOptions.php b/src/RequestOptions.php index 621af75..5b6dc2f 100644 --- a/src/RequestOptions.php +++ b/src/RequestOptions.php @@ -17,7 +17,7 @@ use const Stagehand\Core\OMIT as omit; /** - * @phpstan-type request_options = array{ + * @phpstan-type RequestOptionShape = array{ * timeout?: float|null, * maxRetries?: int|null, * initialRetryDelay?: float|null, @@ -30,11 +30,11 @@ * streamFactory?: StreamFactoryInterface|null, * requestFactory?: RequestFactoryInterface|null, * } - * @phpstan-type request_opts = null|RequestOptions|request_options + * @phpstan-type RequestOpts = null|RequestOptions|RequestOptionShape */ final class RequestOptions implements BaseModel { - /** @use SdkModel */ + /** @use SdkModel */ use SdkModel; #[Property] @@ -78,7 +78,7 @@ public function __construct() } /** - * @param request_opts|null $options + * @param RequestOpts|null $options */ public static function parse(RequestOptions|array|null ...$options): self { From 8d69ed6022b6f8a828e70b7c3ba0795f66150c8d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 05:02:31 +0000 Subject: [PATCH 29/29] release: 0.3.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 46 +++++++++++++++++++++++++++++++++++ src/Version.php | 2 +- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 10f3091..6b7b74c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.2.0" + ".": "0.3.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index d4bfbb5..9c1d4fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,51 @@ # Changelog +## 0.3.0 (2026-01-07) + +Full Changelog: [v0.2.0...v0.3.0](https://github.com/browserbase/stagehand-php/compare/v0.2.0...v0.3.0) + +### ⚠ BREAKING CHANGES + +* use aliases for phpstan types + +### Features + +* [STG-1053] [server] Use fastify-zod-openapi + zod v4 for openapi generation ([3d7bdf5](https://github.com/browserbase/stagehand-php/commit/3d7bdf5f97754c73ae6eb48ea8349f2c8ffc66a8)) +* Added optional param to force empty object ([7405f84](https://github.com/browserbase/stagehand-php/commit/7405f84d11aec0e4d031da5cce447fe841c77ec3)) +* **api:** manual updates ([9cdfcfd](https://github.com/browserbase/stagehand-php/commit/9cdfcfd1bcbdce9a8c9320b5efac239e5ee8cf6c)) +* **api:** manual updates ([68fe598](https://github.com/browserbase/stagehand-php/commit/68fe598df0ac0f73aa8806ed4730bd4c479f54a6)) +* **api:** manual updates ([c1b5c85](https://github.com/browserbase/stagehand-php/commit/c1b5c857aa25cd839ce1ce448d7148e4eccdffe8)) +* **api:** manual updates ([bbf2825](https://github.com/browserbase/stagehand-php/commit/bbf28250640bcdeaf02f2a40ef93802d7630990d)) +* **api:** manual updates ([f5b7983](https://github.com/browserbase/stagehand-php/commit/f5b7983cab846df088bddc707aa1c8fdaf9d1952)) +* **api:** manual updates ([7d51568](https://github.com/browserbase/stagehand-php/commit/7d515687b0aca206c9124b270a4f1f0ab84fe467)) +* **api:** manual updates ([3aac7a3](https://github.com/browserbase/stagehand-php/commit/3aac7a31a6a32ef739f918fba6effb6081b7c10a)) +* **api:** manual updates ([0501932](https://github.com/browserbase/stagehand-php/commit/050193250e7e1092ba83b97d4735e80328492188)) +* **api:** manual updates ([2748aea](https://github.com/browserbase/stagehand-php/commit/2748aea3da35936913f4643a70fb2aff6f61a562)) +* **api:** manual updates ([7715406](https://github.com/browserbase/stagehand-php/commit/771540668a5d44d36d65b566b8c1cacfc1a0312d)) +* **api:** manual updates ([9c9d8f7](https://github.com/browserbase/stagehand-php/commit/9c9d8f74c362253e3494407a8de53713079ff3d9)) +* **api:** manual updates ([8dac4ee](https://github.com/browserbase/stagehand-php/commit/8dac4ee0f673830cc9f31e6c7971cd6bbf1f049f)) +* improved phpstan type annotations ([95004df](https://github.com/browserbase/stagehand-php/commit/95004df5bf286d7fc8942781a6e69a56e6cefe53)) +* use aliases for phpstan types ([7a4328b](https://github.com/browserbase/stagehand-php/commit/7a4328bfa32b6475cb2cbf1da56cb9d2d1fef514)) + + +### Bug Fixes + +* support arrays in query param construction ([4b195d7](https://github.com/browserbase/stagehand-php/commit/4b195d7ecfae72625b33ce440cd9bb83aa6deeea)) + + +### Chores + +* **internal:** codegen related update ([79b8f76](https://github.com/browserbase/stagehand-php/commit/79b8f76ee409f5a35cc742496109e803138554b1)) +* **internal:** codegen related update ([96c0813](https://github.com/browserbase/stagehand-php/commit/96c0813ae699b18ce127aa6f693009cc2f3d63b2)) +* **internal:** codegen related update ([3ce08d1](https://github.com/browserbase/stagehand-php/commit/3ce08d172eba2c771edcd7d7cd81fdc461547c8b)) +* **internal:** codegen related update ([8935e42](https://github.com/browserbase/stagehand-php/commit/8935e42bd30fb4d0a81a211b11c098181404e360)) +* **internal:** refactor auth by moving concern from base client into client ([ccced14](https://github.com/browserbase/stagehand-php/commit/ccced14ea53cfa8120ab9226eb84465703eb7f63)) + + +### Documentation + +* add more examples ([1a0904d](https://github.com/browserbase/stagehand-php/commit/1a0904d4498d41422c6a341ffdbcefcb9f5710c1)) + ## 0.2.0 (2025-12-16) Full Changelog: [v0.1.0...v0.2.0](https://github.com/browserbase/stagehand-php/compare/v0.1.0...v0.2.0) diff --git a/src/Version.php b/src/Version.php index 1473d1e..eaaedcb 100644 --- a/src/Version.php +++ b/src/Version.php @@ -5,5 +5,5 @@ namespace Stagehand; // x-release-please-start-version -const VERSION = '0.2.0'; +const VERSION = '0.3.0'; // x-release-please-end