diff --git a/src/linkup/_client.py b/src/linkup/_client.py index d95616d..6a885a3 100644 --- a/src/linkup/_client.py +++ b/src/linkup/_client.py @@ -535,11 +535,13 @@ def research( The newly created research task, with "pending" status and no output. Raises: - TypeError: If structured_output_schema is not a string, dictionary, or - pydantic.BaseModel when provided. + TypeError: If structured_output_schema is not provided when output_type is + "structured", or if it is not a string, dictionary, or pydantic.BaseModel when + provided. LinkupInvalidRequestError: If the request parameters are invalid. LinkupAuthenticationError: If the Linkup API key is invalid. LinkupInsufficientCreditError: If you have run out of credit. + LinkupBudgetLimitExceededError: If the API key has reached its configured budget limit. LinkupTimeoutError: If the request times out. """ params = self._get_research_params( @@ -606,11 +608,13 @@ async def async_research( The newly created research task, with "pending" status and no output. Raises: - TypeError: If structured_output_schema is not a string, dictionary, or - pydantic.BaseModel when provided. + TypeError: If structured_output_schema is not provided when output_type is + "structured", or if it is not a string, dictionary, or pydantic.BaseModel when + provided. LinkupInvalidRequestError: If the request parameters are invalid. LinkupAuthenticationError: If the Linkup API key is invalid. LinkupInsufficientCreditError: If you have run out of credit. + LinkupBudgetLimitExceededError: If the API key has reached its configured budget limit. LinkupTimeoutError: If the request times out. """ params = self._get_research_params( @@ -1459,6 +1463,11 @@ def _get_research_params( exclude_domains: list[str] | None, include_domains: list[str] | None, ) -> dict[str, str | bool | list[str]]: + if output_type == "structured" and structured_output_schema is None: + raise TypeError( + "structured_output_schema must be provided when output_type is 'structured'" + ) + params: dict[str, str | bool | list[str]] = { "q": query, "outputType": output_type, diff --git a/tests/unit/client_test.py b/tests/unit/client_test.py index bb438b0..39d2405 100644 --- a/tests/unit/client_test.py +++ b/tests/unit/client_test.py @@ -718,6 +718,17 @@ def test_research(mocker: MockerFixture, client: linkup.Client) -> None: ) +def test_research_structured_output_requires_schema(client: linkup.Client) -> None: + with pytest.raises( + TypeError, + match="structured_output_schema must be provided", + ): + client.research( + query="query", + output_type="structured", + ) + + def test_get_research_structured_output_keeps_sourced_answer_shape_raw( mocker: MockerFixture, client: linkup.Client ) -> None: @@ -804,6 +815,20 @@ async def test_async_research(mocker: MockerFixture, client: linkup.Client) -> N assert research_response.input.structured_output_schema == {"type": "object"} +@pytest.mark.asyncio +async def test_async_research_structured_output_requires_schema( + client: linkup.Client, +) -> None: + with pytest.raises( + TypeError, + match="structured_output_schema must be provided", + ): + await client.async_research( + query="query", + output_type="structured", + ) + + def test_research_with_iso_datetime_string_dates( mocker: MockerFixture, client: linkup.Client ) -> None: