diff --git a/CHANGELOG.md b/CHANGELOG.md index 176a677b..73173a7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,11 +11,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### New features - -* `ChatOpenAI()`, `ChatAnthropic()`, and `ChatGoogle()` gain a new `reasoning` parameter to easily opt-into, and fully customize, reasoning capabilities. (#202) +* `ChatOpenAI()`, `ChatAnthropic()`, and `ChatGoogle()` gain a new `reasoning` parameter to easily opt-into, and fully customize, reasoning capabilities. (#202) * A new `ContentThinking` content type was added and captures the "thinking" portion of a reasoning model. (#192) * Added support for built-in provider tools via a new `ToolBuiltIn` class. This enables provider-specific functionality like OpenAI's image generation to be registered and used as tools. Built-in tools pass raw provider definitions directly to the API rather than wrapping Python functions. (#214) * `ChatGoogle()` gains basic support for image generation. (#214) +* New `tool_web_search()` and `tool_web_fetch()` functions provide provider-agnostic access to built-in web search and URL fetch tools: + * `tool_web_search()` is supported by OpenAI, Claude (Anthropic), and Google (Gemini). + * `tool_web_fetch()` is supported by Claude (requires beta header) and Google. + * New content types `ContentToolRequestSearch`, `ContentToolResponseSearch`, `ContentToolRequestFetch`, and `ContentToolResponseFetch` capture web tool interactions. * `ChatOpenAI()` and `ChatAzureOpenAI()` gain a new `service_tier` parameter to request a specific service tier (e.g., `"flex"` for slower/cheaper or `"priority"` for faster/more expensive). (#204) * `Chat` and `Turn` now have a `_repr_markdown_` method and an overall improved `repr()` experience. (#245) diff --git a/CLAUDE.md b/CLAUDE.md index 696e417c..ad512626 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -51,6 +51,14 @@ The project uses `uv` for package management and Make for common tasks: 4. **Content-Based Messaging**: All communication uses structured `Content` objects rather than raw strings 5. **Tool Integration**: Seamless function calling with automatic JSON schema generation from Python type hints +### Typing Best Practices + +This project prioritizes strong typing that leverages provider SDK types directly: + +- **Use provider SDK types**: Import and use types from `openai.types`, `anthropic.types`, `google.genai.types`, etc. rather than creating custom TypedDicts or dataclasses that mirror them. This ensures compatibility with SDK updates and provides better IDE support. +- **Use `@overload` for provider-specific returns**: When a method returns different types based on a provider argument, use `@overload` with `Literal` types to give callers precise return type information. +- **Explore SDK types interactively**: Use `python -c "from .types import ; print(.__annotations__)"` to inspect available fields and nested types when implementing provider-specific features. + ### Testing Structure - Tests are organized by component (e.g., `test_provider_openai.py`, `test_tools.py`) diff --git a/chatlas/__init__.py b/chatlas/__init__.py index 76cdea52..91e25672 100644 --- a/chatlas/__init__.py +++ b/chatlas/__init__.py @@ -35,6 +35,7 @@ from ._provider_snowflake import ChatSnowflake from ._tokens import token_usage from ._tools import Tool, ToolBuiltIn, ToolRejectError +from ._tools_builtin import tool_web_fetch, tool_web_search from ._turn import AssistantTurn, SystemTurn, Turn, UserTurn try: @@ -86,6 +87,8 @@ "Tool", "ToolBuiltIn", "ToolRejectError", + "tool_web_fetch", + "tool_web_search", "Turn", "UserTurn", "SystemTurn", diff --git a/chatlas/_content.py b/chatlas/_content.py index 96a20b9d..fe04739c 100644 --- a/chatlas/_content.py +++ b/chatlas/_content.py @@ -132,6 +132,10 @@ def from_tool(cls, tool: "Tool | ToolBuiltIn") -> "ToolInfo": "json", "pdf", "thinking", + "web_search_request", + "web_search_results", + "web_fetch_request", + "web_fetch_results", ] """ A discriminated union of all content types. @@ -622,6 +626,103 @@ def tagify(self): return HTML(html) +class ContentToolRequestSearch(Content): + """ + A web search request from the model. + + This content type represents the model's request to search the web. + It's automatically generated when a built-in web search tool is used. + + Parameters + ---------- + query + The search query. + extra + The raw provider-specific response data. + """ + + query: str + extra: Optional[dict[str, Any]] = None + + content_type: ContentTypeEnum = "web_search_request" + + def __str__(self): + return f"[web search request]: {self.query!r}" + + +class ContentToolResponseSearch(Content): + """ + Web search results from the model. + + This content type represents the results of a web search. + It's automatically generated when a built-in web search tool returns results. + + Parameters + ---------- + urls + The URLs returned by the search. + extra + The raw provider-specific response data. + """ + + urls: list[str] + extra: Optional[dict[str, Any]] = None + + content_type: ContentTypeEnum = "web_search_results" + + def __str__(self): + url_list = "\n".join(f"* {url}" for url in self.urls) + return f"[web search results]:\n{url_list}" + + +class ContentToolRequestFetch(Content): + """ + A web fetch request from the model. + + This content type represents the model's request to fetch a URL. + It's automatically generated when a built-in web fetch tool is used. + + Parameters + ---------- + url + The URL to fetch. + extra + The raw provider-specific response data. + """ + + url: str + extra: Optional[dict[str, Any]] = None + + content_type: ContentTypeEnum = "web_fetch_request" + + def __str__(self): + return f"[web fetch request]: {self.url}" + + +class ContentToolResponseFetch(Content): + """ + Web fetch results from the model. + + This content type represents the results of fetching a URL. + It's automatically generated when a built-in web fetch tool returns results. + + Parameters + ---------- + url + The URL that was fetched. + extra + The raw provider-specific response data. + """ + + url: str + extra: Optional[dict[str, Any]] = None + + content_type: ContentTypeEnum = "web_fetch_results" + + def __str__(self): + return f"[web fetch result]: {self.url}" + + ContentUnion = Union[ ContentText, ContentImageRemote, @@ -631,6 +732,10 @@ def tagify(self): ContentJson, ContentPDF, ContentThinking, + ContentToolRequestSearch, + ContentToolResponseSearch, + ContentToolRequestFetch, + ContentToolResponseFetch, ] @@ -661,6 +766,14 @@ def create_content(data: dict[str, Any]) -> ContentUnion: return ContentPDF.model_validate(data) elif ct == "thinking": return ContentThinking.model_validate(data) + elif ct == "web_search_request": + return ContentToolRequestSearch.model_validate(data) + elif ct == "web_search_results": + return ContentToolResponseSearch.model_validate(data) + elif ct == "web_fetch_request": + return ContentToolRequestFetch.model_validate(data) + elif ct == "web_fetch_results": + return ContentToolResponseFetch.model_validate(data) else: raise ValueError(f"Unknown content type: {ct}") diff --git a/chatlas/_provider_anthropic.py b/chatlas/_provider_anthropic.py index cfb051e3..7a95c0de 100644 --- a/chatlas/_provider_anthropic.py +++ b/chatlas/_provider_anthropic.py @@ -27,6 +27,10 @@ ContentText, ContentThinking, ContentToolRequest, + ContentToolRequestFetch, + ContentToolRequestSearch, + ContentToolResponseFetch, + ContentToolResponseSearch, ContentToolResult, ) from ._logging import log_model_default @@ -39,6 +43,7 @@ ) from ._tokens import get_price_info from ._tools import Tool, ToolBuiltIn, basemodel_to_param_schema +from ._tools_builtin import ToolWebFetch, ToolWebSearch from ._turn import AssistantTurn, SystemTurn, Turn, UserTurn, user_turn from ._utils import split_http_client_kwargs @@ -494,6 +499,11 @@ def stream_merge_chunks(self, completion, chunk): elif chunk.delta.type == "signature_delta": this_content = cast("ThinkingBlock", this_content) this_content.signature += chunk.delta.signature + elif chunk.delta.type == "citations_delta": + # https://docs.claude.com/en/docs/build-with-claude/citations#streaming-support + # Accumulate citations on the content block + if hasattr(this_content, "citations"): + this_content.citations.append(chunk.delta.citation) # type: ignore elif chunk.type == "content_block_stop": this_content = completion.content[chunk.index] if this_content.type == "tool_use" and isinstance(this_content.input, str): @@ -695,11 +705,28 @@ def _as_content_block(content: Content) -> "ContentBlockParam": "thinking": content.thinking, "signature": extra.get("signature", ""), } + elif isinstance( + content, + ( + ContentToolRequestSearch, + ContentToolResponseSearch, + ContentToolRequestFetch, + ContentToolResponseFetch, + ), + ): + # extra contains the full original content block param + return cast("ContentBlockParam", content.extra) raise ValueError(f"Unknown content type: {type(content)}") @staticmethod def _anthropic_tool_schema(tool: "Tool | ToolBuiltIn") -> "ToolUnionParam": + if isinstance(tool, ToolWebSearch): + return tool.get_definition("anthropic") + if isinstance(tool, ToolWebFetch): + # N.B. seems the return type here (BetaWebFetchTool20250910Param) is + # not a member of ToolUnionParam since it's still in beta? + return tool.get_definition("anthropic") # type: ignore if isinstance(tool, ToolBuiltIn): return tool.definition # type: ignore @@ -757,6 +784,76 @@ def _as_turn(self, completion: Message, has_data_model=False) -> AssistantTurn: extra={"signature": content.signature}, ) ) + elif content.type == "server_tool_use": + # Unfortunately, content.model_dump() includes fields like "url" + # that aren't acceptable as API input, so we manually construct + # the extra dict + if isinstance(content.input, str): + input_data = orjson.loads(content.input) + else: + input_data = content.input + + extra = { + "type": content.type, + "id": content.id, + "name": content.name, + "input": input_data, + } + # https://docs.claude.com/en/docs/agents-and-tools/tool-use/web-search-tool#response + if content.name == "web_search": + contents.append( + ContentToolRequestSearch( + query=str(input_data.get("query", "")), + extra=extra, + ) + ) + # https://docs.claude.com/en/docs/agents-and-tools/tool-use/web-fetch-tool#response + elif content.name == "web_fetch": + # N.B. type checker thinks this is unreachable due to + # ToolUnionParam not including BetaWebFetchTool20250910Param + # yet + contents.append( + ContentToolRequestFetch( + url=str(input_data.get("url", "")), + extra=extra, + ) + ) + else: + raise ValueError(f"Unknown server tool: {content.name}") + elif content.type == "web_search_tool_result": + # https://docs.claude.com/en/docs/agents-and-tools/tool-use/web-search-tool#response + urls: list[str] = [] + if isinstance(content.content, list): + urls = [x.url for x in content.content] + contents.append( + ContentToolResponseSearch( + urls=urls, + extra=content.model_dump(), + ) + ) + elif content.type == "web_fetch_tool_result": + # N.B. type checker thinks this is unreachable due to + # ToolUnionParam not including BetaWebFetchTool20250910Param + # yet. Also, at run-time, the SDK is currently giving non-sense + # of type(content) == TextBlock, but it doesn't even fit that + # shape?!? Anyway, content.content has a dict with the content + # we want. + content_fetch = cast("dict", getattr(content, "content", {})) + if not content_fetch: + raise ValueError( + "web_fetch_tool_result content is empty. Please report this issue." + ) + extra = { + "type": "web_fetch_tool_result", + "tool_use_id": content.tool_use_id, # type: ignore + "content": content_fetch, + } + contents.append( + ContentToolResponseFetch( + url=content_fetch.get("url", "failed"), + extra=extra, + ) + ) return AssistantTurn( contents, diff --git a/chatlas/_provider_google.py b/chatlas/_provider_google.py index 700a5e96..08815ffa 100644 --- a/chatlas/_provider_google.py +++ b/chatlas/_provider_google.py @@ -22,6 +22,7 @@ from ._provider import ModelInfo, Provider, StandardModelParamNames, StandardModelParams from ._tokens import get_price_info from ._tools import Tool, ToolBuiltIn +from ._tools_builtin import ToolWebFetch, ToolWebSearch from ._turn import AssistantTurn, SystemTurn, Turn, UserTurn, user_turn if TYPE_CHECKING: @@ -295,7 +296,11 @@ def _chat_perform_args( data_model: Optional[type[BaseModel]] = None, kwargs: Optional["SubmitInputArgs"] = None, ) -> "SubmitInputArgs": - from google.genai.types import FunctionDeclaration, GenerateContentConfig + from google.genai.types import ( + FunctionDeclaration, + GenerateContentConfig, + ToolListUnion, + ) from google.genai.types import Tool as GoogleTool kwargs_full: "SubmitInputArgs" = { @@ -319,20 +324,30 @@ def _chat_perform_args( config.response_mime_type = "application/json" if tools: - config.tools = [ - GoogleTool( - function_declarations=[ - FunctionDeclaration.from_callable( - client=self._client._api_client, - callable=tool.func, - ) - for tool in tools.values() - # TODO: to support built-in tools, we may need a way to make - # tool names (e.g., google_search to google.genai.types.GoogleSearch()) - if isinstance(tool, Tool) - ] - ) - ] + google_tools: ToolListUnion = [] + for tool in tools.values(): + if isinstance(tool, ToolWebSearch): + gtool = GoogleTool(google_search=tool.get_definition("google")) + google_tools.append(gtool) + elif isinstance(tool, ToolWebFetch): + gtool = GoogleTool(url_context=tool.get_definition("google")) + google_tools.append(gtool) + elif isinstance(tool, ToolBuiltIn): + gtool = GoogleTool.model_validate(tool.definition) + google_tools.append(gtool) + else: + gtool = GoogleTool( + function_declarations=[ + FunctionDeclaration.from_callable( + client=self._client._api_client, + callable=tool.func, + ) + ] + ) + google_tools.append(gtool) + + if google_tools: + config.tools = google_tools kwargs_full["config"] = config diff --git a/chatlas/_provider_openai.py b/chatlas/_provider_openai.py index e1b3e243..5d91920e 100644 --- a/chatlas/_provider_openai.py +++ b/chatlas/_provider_openai.py @@ -18,6 +18,7 @@ ContentText, ContentThinking, ContentToolRequest, + ContentToolRequestSearch, ContentToolResult, ) from ._logging import log_model_default @@ -25,6 +26,7 @@ from ._provider_openai_completions import load_tool_request_args from ._provider_openai_generic import BatchResult, OpenAIAbstractProvider from ._tools import Tool, ToolBuiltIn, basemodel_to_param_schema +from ._tools_builtin import ToolWebFetch, ToolWebSearch from ._turn import AssistantTurn, Turn if TYPE_CHECKING: @@ -235,7 +237,15 @@ def _chat_perform_args( tool_params: list["ToolParam"] = [] for tool in tools.values(): - if isinstance(tool, ToolBuiltIn): + if isinstance(tool, ToolWebSearch): + tool_params.append(tool.get_definition("openai")) + elif isinstance(tool, ToolWebFetch): + raise ValueError( + "Web fetch is currently not natively supported by OpenAI. " + "Consider using the MCP Fetch server instead via chat.register_mcp_tools_stdio_async(). " + "See help(tool_web_fetch) for details." + ) + elif isinstance(tool, ToolBuiltIn): tool_params.append(cast("ToolParam", tool.definition)) else: schema = tool.schema @@ -409,6 +419,20 @@ def _response_as_turn(completion: Response, has_data_model: bool) -> AssistantTu ) ) + elif output.type == "web_search_call": + if output.action.type != "search": + raise ValueError( + f"Unsupported web search action type: {output.action.type}" + "Please file a feature request if you need this supported." + ) + # https://platform.openai.com/docs/guides/tools-web-search#output-and-citations + contents.append( + ContentToolRequestSearch( + query=output.action.query, + extra=output.model_dump(), + ) + ) + else: raise ValueError(f"Unknown output type: {output.type}") @@ -530,6 +554,8 @@ def as_input_param(content: Content, role: Role) -> "ResponseInputItemParam": "name": content.name, "arguments": orjson.dumps(content.arguments).decode("utf-8"), } + elif isinstance(content, ContentToolRequestSearch): + return cast("ResponseInputItemParam", content.extra) else: raise ValueError(f"Unsupported content type: {type(content)}") diff --git a/chatlas/_tools_builtin.py b/chatlas/_tools_builtin.py new file mode 100644 index 00000000..c77322c7 --- /dev/null +++ b/chatlas/_tools_builtin.py @@ -0,0 +1,627 @@ +""" +Built-in provider tools for web search and fetch. + +These classes provide a provider-agnostic way to configure built-in tools +like web search and URL fetching. Each provider translates these configurations +into their specific API format. +""" + +from __future__ import annotations + +import warnings +from typing import TYPE_CHECKING, Literal, Optional, overload + +from ._tools import ToolBuiltIn + +if TYPE_CHECKING: + from anthropic.types import WebSearchTool20250305Param + from anthropic.types.beta import BetaWebFetchTool20250910Param + from anthropic.types.beta.beta_citations_config_param import ( + BetaCitationsConfigParam, + ) + from anthropic.types.cache_control_ephemeral_param import ( + CacheControlEphemeralParam, + ) + from google.genai.types import ( + GoogleSearch, + Interval, + PhishBlockThreshold, + UrlContext, + ) + from openai.types.responses import WebSearchToolParam + + from ._typing_extensions import TypedDict + + class UserLocation(TypedDict, total=False): + """User location for localizing search results.""" + + country: str + """Two-letter ISO country code (e.g., 'US', 'GB').""" + city: str + """City name.""" + region: str + """Region/state name.""" + timezone: str + """IANA timezone (e.g., 'America/New_York').""" + + +__all__ = ( + "tool_web_search", + "tool_web_fetch", + "ToolWebSearch", + "ToolWebFetch", +) + + +def _warn_unsupported(param_name: str, provider: str) -> None: + """Warn that a parameter is not supported by a provider.""" + warnings.warn( + f"{param_name} is not supported by {provider} and will be ignored.", + UserWarning, + stacklevel=3, + ) + + +class ToolWebSearch(ToolBuiltIn): + """ + A provider-agnostic web search tool configuration. + + This class stores configuration for web search functionality. Each provider + translates this configuration into their specific API format. + + Parameters + ---------- + allowed_domains + Restrict searches to specific domains (e.g., ['nytimes.com', 'bbc.com']). + Not all providers support this parameter. + blocked_domains + Exclude specific domains from searches. + Only supported by Claude. Cannot be used with allowed_domains. + user_location + Location information to localize search results. + max_uses + Maximum number of searches allowed per request. + Only supported by Claude. + """ + + def __init__( + self, + *, + allowed_domains: Optional[list[str]] = None, + blocked_domains: Optional[list[str]] = None, + user_location: "Optional[UserLocation]" = None, + max_uses: Optional[int] = None, + ): + if allowed_domains and blocked_domains: + raise ValueError( + "Cannot specify both allowed_domains and blocked_domains. " + "Use one or the other." + ) + + self.allowed_domains = allowed_domains + self.blocked_domains = blocked_domains + self.user_location = user_location + self.max_uses = max_uses + + # Initialize ToolBuiltIn with placeholder definition + # (providers will use get_definition() to get the actual definition) + super().__init__(name="web_search", definition={}) + + @overload + def get_definition( + self, + provider_name: Literal["openai"], + *, + search_context_size: "Literal['low', 'medium', 'high'] | None" = None, + ) -> "WebSearchToolParam": ... + + @overload + def get_definition( + self, + provider_name: Literal["anthropic"], + *, + cache_control: "CacheControlEphemeralParam | None" = None, + ) -> "WebSearchTool20250305Param": ... + + @overload + def get_definition( + self, + provider_name: Literal["google"], + *, + blocking_confidence: "PhishBlockThreshold | None" = None, + time_range_filter: "Interval | None" = None, + ) -> "GoogleSearch": ... + + def get_definition( + self, + provider_name: Literal["openai", "anthropic", "google"], + *, + # OpenAI-specific + search_context_size: "Literal['low', 'medium', 'high'] | None" = None, + # Anthropic-specific + cache_control: "CacheControlEphemeralParam | None" = None, + # Google-specific + blocking_confidence: "PhishBlockThreshold | None" = None, + time_range_filter: "Interval | None" = None, + ) -> "WebSearchToolParam | WebSearchTool20250305Param | GoogleSearch": + """ + Get the provider-specific tool definition. + + Parameters + ---------- + provider_name + The name of the provider ('openai', 'anthropic', or 'google'). + search_context_size + OpenAI only. Amount of search context: 'low', 'medium', or 'high'. + cache_control + Anthropic only. Cache control settings for prompt caching. + blocking_confidence + Google only. Threshold for blocking phishing sites. + time_range_filter + Google only. Filter search results to a specific time range. + + Returns + ------- + : + The provider-specific tool definition. + """ + if provider_name == "openai": + if self.blocked_domains: + _warn_unsupported("blocked_domains", "OpenAI") + if self.max_uses is not None: + _warn_unsupported("max_uses", "OpenAI") + return self._openai_definition( + allowed_domains=self.allowed_domains, + user_location=self.user_location, + search_context_size=search_context_size, + ) + elif provider_name == "anthropic": + return self._anthropic_definition( + allowed_domains=self.allowed_domains, + blocked_domains=self.blocked_domains, + user_location=self.user_location, + max_uses=self.max_uses, + cache_control=cache_control, + ) + elif provider_name == "google": + if self.allowed_domains: + _warn_unsupported("allowed_domains", "Google") + if self.user_location: + _warn_unsupported("user_location", "Google") + if self.max_uses is not None: + _warn_unsupported("max_uses", "Google") + return self._google_definition( + blocked_domains=self.blocked_domains, + blocking_confidence=blocking_confidence, + time_range_filter=time_range_filter, + ) + else: + raise ValueError( + f"Web search is not supported for provider '{provider_name}'. " + "Supported providers: openai, anthropic, google." + ) + + @staticmethod + def _openai_definition( + *, + allowed_domains: Optional[list[str]], + user_location: "Optional[UserLocation]", + search_context_size: "Literal['low', 'medium', 'high'] | None" = None, + ) -> "WebSearchToolParam": + """Generate OpenAI web search tool definition.""" + # https://platform.openai.com/docs/guides/tools-web-search + definition: WebSearchToolParam = {"type": "web_search"} + + if search_context_size is not None: + definition["search_context_size"] = search_context_size + + if allowed_domains: + domains = [ + d.removeprefix("https://").removeprefix("http://") + for d in allowed_domains + ] + definition["filters"] = {"allowed_domains": domains} + + if user_location: + definition["user_location"] = { + "type": "approximate", + **user_location, + } + + return definition + + @staticmethod + def _anthropic_definition( + *, + allowed_domains: Optional[list[str]], + blocked_domains: Optional[list[str]], + user_location: "Optional[UserLocation]", + max_uses: Optional[int], + cache_control: "CacheControlEphemeralParam | None" = None, + ) -> "WebSearchTool20250305Param": + """Generate Anthropic/Claude web search tool definition.""" + # https://docs.claude.com/en/docs/agents-and-tools/tool-use/web-search-tool + definition: WebSearchTool20250305Param = { + "name": "web_search", + "type": "web_search_20250305", + } + + if max_uses is not None: + definition["max_uses"] = max_uses + if allowed_domains: + definition["allowed_domains"] = allowed_domains + if blocked_domains: + definition["blocked_domains"] = blocked_domains + if user_location: + definition["user_location"] = { + "type": "approximate", + **user_location, + } + if cache_control is not None: + definition["cache_control"] = cache_control + + return definition + + @staticmethod + def _google_definition( + *, + blocked_domains: Optional[list[str]], + blocking_confidence: "PhishBlockThreshold | None" = None, + time_range_filter: "Interval | None" = None, + ) -> "GoogleSearch": + """Generate Google/Gemini web search tool definition.""" + # https://ai.google.dev/gemini-api/docs/google-search + from google.genai.types import GoogleSearch + + return GoogleSearch( + exclude_domains=blocked_domains, + blocking_confidence=blocking_confidence, + time_range_filter=time_range_filter, + ) + + +class ToolWebFetch(ToolBuiltIn): + """ + A provider-agnostic URL fetch tool configuration. + + This class stores configuration for URL fetching functionality. Each provider + translates this configuration into their specific API format. + + Note: Currently supported by Claude and Google. OpenAI does not have a built-in + URL fetch tool. + + Parameters + ---------- + allowed_domains + Restrict fetches to specific domains. + Only supported by Claude. + blocked_domains + Exclude specific domains from fetches. + Only supported by Claude. Cannot be used with allowed_domains. + max_uses + Maximum number of fetches allowed per request. + Only supported by Claude. + """ + + def __init__( + self, + *, + allowed_domains: Optional[list[str]] = None, + blocked_domains: Optional[list[str]] = None, + max_uses: Optional[int] = None, + ): + if allowed_domains and blocked_domains: + raise ValueError( + "Cannot specify both allowed_domains and blocked_domains. " + "Use one or the other." + ) + + # Store configuration + self.allowed_domains = allowed_domains + self.blocked_domains = blocked_domains + self.max_uses = max_uses + + # Initialize ToolBuiltIn with placeholder definition + super().__init__(name="web_fetch", definition={}) + + @overload + def get_definition( + self, + provider_name: Literal["anthropic"], + *, + cache_control: "CacheControlEphemeralParam | None" = None, + citations: "BetaCitationsConfigParam | None" = None, + max_content_tokens: Optional[int] = None, + ) -> "BetaWebFetchTool20250910Param": ... + + @overload + def get_definition( + self, + provider_name: Literal["google"], + ) -> "UrlContext": ... + + def get_definition( + self, + provider_name: Literal["anthropic", "google"], + *, + # Anthropic-specific + cache_control: "CacheControlEphemeralParam | None" = None, + citations: "BetaCitationsConfigParam | None" = None, + max_content_tokens: Optional[int] = None, + ) -> "BetaWebFetchTool20250910Param | UrlContext": + """ + Get the provider-specific tool definition. + + Parameters + ---------- + provider_name + The name of the provider ('anthropic' or 'google'). + cache_control + Anthropic only. Cache control settings for prompt caching. + citations + Anthropic only. Configuration for inline citations. + max_content_tokens + Anthropic only. Maximum content tokens to fetch. + + Returns + ------- + : + The provider-specific tool definition. + """ + if provider_name == "anthropic": + return self._anthropic_definition( + allowed_domains=self.allowed_domains, + blocked_domains=self.blocked_domains, + max_uses=self.max_uses, + cache_control=cache_control, + citations=citations, + max_content_tokens=max_content_tokens, + ) + elif provider_name == "google": + if self.allowed_domains: + _warn_unsupported("allowed_domains", "Google") + if self.blocked_domains: + _warn_unsupported("blocked_domains", "Google") + if self.max_uses is not None: + _warn_unsupported("max_uses", "Google") + return self._google_definition() + else: + raise ValueError( + f"Web fetch is not supported for provider '{provider_name}'. " + "Supported providers: anthropic, google." + ) + + @staticmethod + def _anthropic_definition( + *, + allowed_domains: Optional[list[str]], + blocked_domains: Optional[list[str]], + max_uses: Optional[int], + cache_control: "CacheControlEphemeralParam | None" = None, + citations: "BetaCitationsConfigParam | None" = None, + max_content_tokens: Optional[int] = None, + ) -> "BetaWebFetchTool20250910Param": + """Generate Anthropic/Claude web fetch tool definition.""" + # https://docs.claude.com/en/docs/agents-and-tools/tool-use/web-fetch-tool + definition: BetaWebFetchTool20250910Param = { + "name": "web_fetch", + "type": "web_fetch_20250910", + } + + if max_uses is not None: + definition["max_uses"] = max_uses + if allowed_domains: + definition["allowed_domains"] = allowed_domains + if blocked_domains: + definition["blocked_domains"] = blocked_domains + if cache_control is not None: + definition["cache_control"] = cache_control + if citations is not None: + definition["citations"] = citations + if max_content_tokens is not None: + definition["max_content_tokens"] = max_content_tokens + + return definition + + @staticmethod + def _google_definition() -> "UrlContext": + """Generate Google/Gemini URL fetch tool definition.""" + # https://ai.google.dev/gemini-api/docs/url-context + from google.genai.types import UrlContext + + return UrlContext() + + +def tool_web_search( + *, + allowed_domains: Optional[list[str]] = None, + blocked_domains: Optional[list[str]] = None, + user_location: "Optional[UserLocation]" = None, + max_uses: Optional[int] = None, +) -> ToolWebSearch: + """ + Create a web search tool for use with chat models. + + This function creates a provider-agnostic web search tool that can be + registered with any supported chat provider. The tool allows the model + to search the web for up-to-date information. + + Supported providers: OpenAI, Claude (Anthropic), Google (Gemini) + + Prerequisites + ------------- + - **OpenAI**: Web search is available by default. + - **Claude**: Web search must be enabled in the Anthropic Console by your + organization administrator. It costs extra ($10 per 1,000 searches at + time of writing). + - **Google**: Web search (grounding) is available by default with Gemini. + + Parameters + ---------- + allowed_domains + Restrict searches to specific domains (e.g., `['nytimes.com', 'bbc.com']`). + Supported by OpenAI and Claude. Cannot be used with `blocked_domains`. + blocked_domains + Exclude specific domains from searches. + Supported by Claude and Google. Cannot be used with `allowed_domains`. + user_location + Location information to localize search results. A dictionary with + optional keys: `country` (2-letter ISO code), `city`, `region`, and + `timezone` (IANA timezone like 'America/New_York'). + Supported by OpenAI and Claude. + max_uses + Maximum number of searches allowed per request. + Only supported by Claude. + + Returns + ------- + ToolWebSearch + A web search tool that can be registered with `chat.register_tool()`. + + Examples + -------- + ```python + from chatlas import ChatOpenAI, tool_web_search + + # Basic usage + chat = ChatOpenAI() + chat.register_tool(tool_web_search()) + chat.chat("What are the top news stories today?") + + # With domain restrictions + chat = ChatOpenAI() + chat.register_tool(tool_web_search(allowed_domains=["nytimes.com", "bbc.com"])) + chat.chat("What's happening in the economy?") + + # With location for localized results + chat = ChatOpenAI() + chat.register_tool( + tool_web_search( + user_location={ + "country": "US", + "city": "San Francisco", + "timezone": "America/Los_Angeles", + } + ) + ) + chat.chat("What's the weather forecast?") + ``` + + Note + ---- + Not all parameters are supported by all providers: + + - `allowed_domains`: OpenAI, Claude + - `blocked_domains`: Claude, Google + - `user_location`: OpenAI, Claude + - `max_uses`: Claude only + + Unsupported parameters are silently ignored by providers that don't support + them. + """ + return ToolWebSearch( + allowed_domains=allowed_domains, + blocked_domains=blocked_domains, + user_location=user_location, + max_uses=max_uses, + ) + + +def tool_web_fetch( + *, + allowed_domains: Optional[list[str]] = None, + blocked_domains: Optional[list[str]] = None, + max_uses: Optional[int] = None, +) -> ToolWebFetch: + """ + Create a URL fetch tool for use with chat models. + + This function creates a provider-agnostic URL fetch tool that can be + registered with supported chat providers. The tool allows the model to + fetch and analyze content from web URLs. + + Supported providers: Claude (Anthropic), Google (Gemini) + + Prerequisites + ------------- + - **Claude**: The web fetch tool requires the beta header + `anthropic-beta: web-fetch-2025-09-10`. Pass this via the `kwargs` + parameter's `default_headers` option (see examples below). + - **Google**: URL context is available by default with Gemini. + + Parameters + ---------- + allowed_domains + Restrict fetches to specific domains. + Only supported by Claude. + blocked_domains + Exclude specific domains from fetches. + Only supported by Claude. Cannot be used with `allowed_domains`. + max_uses + Maximum number of fetches allowed per request. + Only supported by Claude. + + Returns + ------- + ToolWebFetch + A URL fetch tool that can be registered with `chat.register_tool()`. + + Examples + -------- + ```python + from chatlas import ChatAnthropic, tool_web_fetch + + # Basic usage with Claude (requires beta header) + chat = ChatAnthropic( + kwargs={"default_headers": {"anthropic-beta": "web-fetch-2025-09-10"}} + ) + chat.register_tool(tool_web_fetch()) + chat.chat("Summarize the content at https://en.wikipedia.org/wiki/Python") + + # With domain restrictions + chat = ChatAnthropic( + kwargs={"default_headers": {"anthropic-beta": "web-fetch-2025-09-10"}} + ) + chat.register_tool(tool_web_fetch(allowed_domains=["wikipedia.org", "python.org"])) + chat.chat("Summarize the content at https://en.wikipedia.org/wiki/Guido_van_Rossum") + ``` + + Note + ---- + For Claude, the model can only fetch URLs that appear in the conversation + context (user messages or previous tool results). For security reasons, + Claude cannot dynamically construct URLs to fetch. + + Using with OpenAI (and other providers) + --------------------------------------- + OpenAI does not have a built-in URL fetch tool. For OpenAI and other + providers without native fetch support, use the MCP Fetch server from + the Model Context Protocol project: + https://github.com/modelcontextprotocol/servers/tree/main/src/fetch + + ```python + import asyncio + from chatlas import ChatOpenAI + + + async def main(): + chat = ChatOpenAI() + await chat.register_mcp_tools_stdio_async( + command="uvx", + args=["mcp-server-fetch"], + ) + await chat.chat_async("Summarize the content at https://www.python.org") + await chat.cleanup_mcp_tools() + + + asyncio.run(main()) + ``` + + This approach works with any provider, making it useful for consistent + behavior across different LLM backends. + """ + return ToolWebFetch( + allowed_domains=allowed_domains, + blocked_domains=blocked_domains, + max_uses=max_uses, + ) diff --git a/chatlas/types/__init__.py b/chatlas/types/__init__.py index 7b94e392..782b7e11 100644 --- a/chatlas/types/__init__.py +++ b/chatlas/types/__init__.py @@ -11,6 +11,10 @@ ContentJson, ContentText, ContentToolRequest, + ContentToolRequestFetch, + ContentToolRequestSearch, + ContentToolResponseFetch, + ContentToolResponseSearch, ContentToolResult, ImageContentTypes, ToolAnnotations, @@ -30,6 +34,10 @@ "ContentText", "ContentToolRequest", "ContentToolResult", + "ContentToolRequestFetch", + "ContentToolResponseFetch", + "ContentToolRequestSearch", + "ContentToolResponseSearch", "StructuredChatResult", "ChatResponse", "ChatResponseAsync", diff --git a/docs/_quarto.yml b/docs/_quarto.yml index 9754a89f..f4fd7cda 100644 --- a/docs/_quarto.yml +++ b/docs/_quarto.yml @@ -160,6 +160,11 @@ quartodoc: contents: - Tool - ToolRejectError + - title: Built-in tools + desc: Provider-agnostic access to built-in web search and fetch capabilities. + contents: + - tool_web_search + - tool_web_fetch - title: Parallel and batch chat desc: Submit multiple chats in parallel (fast) or one batch (cheap) contents: @@ -198,6 +203,10 @@ quartodoc: - types.ContentText - types.ContentToolRequest - types.ContentToolResult + - types.ContentToolRequestSearch + - types.ContentToolResponseSearch + - types.ContentToolRequestFetch + - types.ContentToolResponseFetch - types.ChatResponse - types.ChatResponseAsync - types.ImageContentTypes diff --git a/docs/get-started/tools.qmd b/docs/get-started/tools.qmd index b5f44196..a4e2f3ee 100644 --- a/docs/get-started/tools.qmd +++ b/docs/get-started/tools.qmd @@ -88,6 +88,28 @@ You'll learn more about this in [custom displays](../tool-calling/displays.qmd) ::: +### Built-in tools + +Some providers offer built-in tools that run on their servers, such as web search and URL fetching. +chatlas provides provider-agnostic access to these capabilities via [`tool_web_search()`](../reference/tool_web_search.qmd) and [`tool_web_fetch()`](../reference/tool_web_fetch.qmd): + +```python +from chatlas import ChatOpenAI, tool_web_search + +chat = ChatOpenAI() +chat.register_tool(tool_web_search()) +chat.chat("What are the top news stories today?") +``` + +These tools translate to each provider's native format automatically. +See the function reference for supported providers and configuration options. + +::: callout-note +For providers without native fetch support (like OpenAI), you can use the [MCP Fetch server](https://github.com/modelcontextprotocol/servers/tree/main/src/fetch) via `register_mcp_tools_stdio_async()`. +See the [MCP tools guide](../misc/mcp-tools.qmd) for more information. +::: + + ### Tool errors When a tool function is called, it may fail for various reasons, such as network issues, invalid input, or unexpected exceptions. diff --git a/tests/_vcr/test_provider_anthropic/test_anthropic_web_fetch.yaml b/tests/_vcr/test_provider_anthropic/test_anthropic_web_fetch.yaml new file mode 100644 index 00000000..05c4aba9 --- /dev/null +++ b/tests/_vcr/test_provider_anthropic/test_anthropic_web_fetch.yaml @@ -0,0 +1,415 @@ +interactions: +- request: + body: '{"max_tokens": 4096, "messages": [{"role": "user", "content": [{"text": + "What''s the first movie listed on https://rvest.tidyverse.org/articles/starwars.html?", + "type": "text", "cache_control": {"type": "ephemeral", "ttl": "5m"}}]}], "model": + "claude-haiku-4-5-20251001", "stream": true, "tools": [{"name": "web_fetch", + "type": "web_fetch_20250910"}]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '327' + Content-Type: + - application/json + Host: + - api.anthropic.com + X-Stainless-Async: + - 'false' + anthropic-beta: + - web-fetch-2025-09-10 + anthropic-version: + - '2023-06-01' + x-stainless-read-timeout: + - '600' + x-stainless-timeout: + - NOT_GIVEN + method: POST + uri: https://api.anthropic.com/v1/messages + response: + body: + string: "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-haiku-4-5-20251001\",\"id\":\"msg_01Gf2Wgf7Hrr2aPoHKwWnGNc\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"usage\":{\"input_tokens\":1055,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"cache_creation\":{\"ephemeral_5m_input_tokens\":0,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":3,\"service_tier\":\"standard\"}} + \ }\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"I'll + fetch\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\" + that\"} }\n\nevent: ping\ndata: {\"type\": \"ping\"}\n\nevent: content_block_delta\ndata: + {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\" + page\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\" + for\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\" + you.\"} }\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0 + \ }\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"server_tool_use\",\"id\":\"srvtoolu_01WD9r1pi8iKmUkg946XxKiw\",\"name\":\"web_fetch\",\"input\":{}} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"ur\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"l\\\": + \\\"htt\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"ps\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"://rvest.t\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"idyverse.or\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"g/art\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"icles/sta\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"rwars.html\\\"}\"} + }\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1 + \ }\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":2,\"content_block\":{\"type\":\"web_fetch_tool_result\",\"tool_use_id\":\"srvtoolu_01WD9r1pi8iKmUkg946XxKiw\",\"content\":{\"type\":\"web_fetch_result\",\"url\":\"https://rvest.tidyverse.org/articles/starwars.html\",\"retrieved_at\":\"2026-01-02T21:08:24.211000+00:00\",\"content\":{\"type\":\"document\",\"source\":{\"type\":\"text\",\"media_type\":\"text/plain\",\"data\":\"Star + Wars films (static HTML) \u2022 rvest\\n\\n\\n[Skip to content](#container)\\n\\n\\n[rvest](../index.html)\\n1.0.5\\n\\n\\n\\n\\n* + [Get started](../articles/rvest.html)\\n* [Reference](../reference/index.html)\\n* + Articles\\n + [SelectorGadget](../articles/selectorgadget.html)\\n + [Star + Wars films (dynamic HTML)](../articles/starwars-dynamic.html)\\n + [Star + Wars films (static HTML)](../articles/starwars.html)\\n* News\\n + ###### + Releases\\n + [Version 1.0.0](https://www.tidyverse.org/blog/2021/03/rvest-1-0-0/)\\n + \ + [Version 0.3.0](https://blog.rstudio.com/2015/09/24/rvest-0-3-0/)\\n + + [Version 0.1.0](https://blog.rstudio.com/2014/11/24/rvest-easy-web-scraping-with-r/)\\n + \ + ---\\n + [Changelog](../news/index.html)\\n\\n![](../logo.png)\\n\\n# + Star Wars films (static HTML)\\n\\nSource: [`vignettes/starwars.Rmd`](https://github.com/tidyverse/rvest/blob/main/vignettes/starwars.Rmd)\\n\\n`starwars.Rmd`\\n\\nThis + vignette contains some data about the Star Wars films for use in\\nrvest examples + and vignettes.\\n\\n## The Phantom Menace\\n\\nReleased: 1999-05-19\\n\\nDirector: + George Lucas\\n\\nTurmoil has engulfed the Galactic Republic. The taxation + of trade routes\\nto outlying star systems is in dispute.\\n\\nHoping to resolve + the matter with a blockade of deadly battleships, the\\ngreedy Trade Federation + has stopped all shipping to the small planet of\\nNaboo.\\n\\nWhile the Congress + of the Republic endlessly debates this alarming chain\\nof events, the Supreme + Chancellor has secretly dispatched two Jedi\\nKnights, the guardians of peace + and justice in the galaxy, to settle the\\nconflict\u2026.\\n\\n## Attack + of the Clones\\n\\nReleased: 2002-05-16\\n\\nDirector: George Lucas\\n\\nThere + is unrest in the Galactic Senate. Several thousand solar systems\\nhave declared + their intentions to leave the Republic.\\n\\nThis separatist movement, under + the leadership of the mysterious Count\\nDooku, has made it difficult for + the limited number of Jedi Knights to\\nmaintain peace and order in the galaxy.\\n\\nSenator + Amidala, the former Queen of Naboo, is returning to the Galactic\\nSenate + to vote on the critical issue of creating an ARMY OF THE REPUBLIC\\nto assist + the overwhelmed Jedi\u2026.\\n\\n## Revenge of the Sith\\n\\nReleased: 2005-05-19\\n\\nDirector: + George Lucas\\n\\nWar! The Republic is crumbling under attacks by the ruthless + Sith Lord,\\nCount Dooku. There are heroes on both sides. Evil is everywhere.\\n\\nIn + a stunning move, the fiendish droid leader, General Grievous, has\\nswept + into the Republic capital and kidnapped Chancellor Palpatine,\\nleader of + the Galactic Senate.\\n\\nAs the Separatist Droid Army attempts to flee the + besieged capital with\\ntheir valuable hostage, two Jedi Knights lead a desperate + mission to\\nrescue the captive Chancellor\u2026.\\n\\n## A New Hope\\n\\nReleased: + 1977-05-25\\n\\nDirector: George Lucas\\n\\nIt is a period of civil war. Rebel + spaceships, striking from a hidden\\nbase, have won their first victory against + the evil Galactic Empire.\\n\\nDuring the battle, Rebel spies managed to steal + secret plans to the\\nEmpire\u2019s ultimate weapon, the DEATH STAR, an armored + space station with\\nenough power to destroy an entire planet.\\n\\nPursued + by the Empire\u2019s sinister agents, Princess Leia races home aboard\\nher + starship, custodian of the stolen plans that can save her people and\\nrestore + freedom to the galaxy\u2026.\\n\\n## The Empire Strikes Back\\n\\nReleased: + 1980-05-17\\n\\nDirector: Irvin Kershner\\n\\nIt is a dark time for the Rebellion. + Although the Death Star has been\\ndestroyed, Imperial troops have driven + the Rebel forces from their\\nhidden base and pursued them across the galaxy.\\n\\nEvading + the dreaded Imperial Starfleet, a group of freedom fighters led\\nby Luke + Skywalker has established a new secret base on the remote ice\\nworld of Hoth.\\n\\nThe + evil lord Darth Vader, obsessed with finding young Skywalker, has\\ndispatched + thousands of remote probes into the far reaches of space\u2026.\\n\\n## Return + of the Jedi\\n\\nReleased: 1983-05-25\\n\\nDirector: Richard Marquand\\n\\nLuke + Skywalker has returned to his home planet of Tatooine in an attempt\\nto rescue + his friend Han Solo from the clutches of the vile gangster\\nJabba the Hutt.\\n\\nLittle + does Luke know that the GALACTIC EMPIRE has secretly begun\\nconstruction + on a new armored space station even more powerful than the\\nfirst dreaded + Death Star.\\n\\nWhen completed, this ultimate weapon will spell certain doom + for the\\nsmall band of rebels struggling to restore freedom to the galaxy\u2026\\n\\n## + The Force Awakens\\n\\nReleased: 2015-12-11\\n\\nDirector: J. J. Abrams\\n\\nLuke + Skywalker has vanished. In his absence, the sinister FIRST ORDER\\nhas risen + from the ashes of the Empire and will not rest until\\nSkywalker, the last + Jedi, has been destroyed. With the support of the\\nREPUBLIC, General Leia + Organa leads a brave RESISTANCE. She is desperate\\nto find her brother Luke + and gain his help in restoring peace and\\njustice to the galaxy. Leia has + sent her most daring pilot on a secret\\nmission to Jakku, where an old ally + has discovered a clue to Luke\u2019s\\nwhereabouts\u2026.\\n\\n## On this + page\\n\\nDeveloped by [Hadley Wickham](https://hadley.nz), [![Posit](https://www.tidyverse.org/posit-logo.svg)](https://www.posit.co).\\n\\nSite + built with [pkgdown](https://pkgdown.r-lib.org/) 2.1.3.\"},\"title\":\"Star + Wars films (static HTML)\"}}} }\n\nevent: content_block_stop\ndata: + {\"type\":\"content_block_stop\",\"index\":2 }\n\nevent: content_block_start\ndata: + {\"type\":\"content_block_start\",\"index\":3,\"content_block\":{\"type\":\"text\",\"text\":\"\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":3,\"delta\":{\"type\":\"text_delta\",\"text\":\"The\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":3,\"delta\":{\"type\":\"text_delta\",\"text\":\" + first\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":3,\"delta\":{\"type\":\"text_delta\",\"text\":\" + movie\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":3,\"delta\":{\"type\":\"text_delta\",\"text\":\" + liste\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":3,\"delta\":{\"type\":\"text_delta\",\"text\":\"d + on\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":3,\"delta\":{\"type\":\"text_delta\",\"text\":\" + that\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":3,\"delta\":{\"type\":\"text_delta\",\"text\":\" + page is **\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":3,\"delta\":{\"type\":\"text_delta\",\"text\":\"The\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":3,\"delta\":{\"type\":\"text_delta\",\"text\":\" + Phantom Menace**,\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":3,\"delta\":{\"type\":\"text_delta\",\"text\":\" + release\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":3,\"delta\":{\"type\":\"text_delta\",\"text\":\"d + on\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":3,\"delta\":{\"type\":\"text_delta\",\"text\":\" + \"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":3,\"delta\":{\"type\":\"text_delta\",\"text\":\"1999-05-19\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":3,\"delta\":{\"type\":\"text_delta\",\"text\":\" + \"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":3,\"delta\":{\"type\":\"text_delta\",\"text\":\"an\"}}\n\nevent: + content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":3,\"delta\":{\"type\":\"text_delta\",\"text\":\"d + directed by George Lucas.\"} }\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":3}\n\nevent: + message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\",\"stop_sequence\":null},\"usage\":{\"input_tokens\":3727,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"output_tokens\":115,\"server_tool_use\":{\"web_search_requests\":0,\"web_fetch_requests\":1}} + \ }\n\nevent: message_stop\ndata: {\"type\":\"message_stop\" }\n\n" + headers: + CF-RAY: + - 9b7d96e6dc68b3ad-DEN + Cache-Control: + - no-cache + Connection: + - keep-alive + Content-Type: + - text/event-stream; charset=utf-8 + Date: + - Fri, 02 Jan 2026 22:10:58 GMT + Server: + - cloudflare + Transfer-Encoding: + - chunked + X-Robots-Tag: + - none + anthropic-ratelimit-input-tokens-limit: + - '4000000' + anthropic-ratelimit-input-tokens-remaining: + - '3999000' + anthropic-ratelimit-input-tokens-reset: + - '2026-01-02T22:10:57Z' + anthropic-ratelimit-output-tokens-limit: + - '800000' + anthropic-ratelimit-output-tokens-remaining: + - '800000' + anthropic-ratelimit-output-tokens-reset: + - '2026-01-02T22:10:57Z' + anthropic-ratelimit-requests-limit: + - '4000' + anthropic-ratelimit-requests-remaining: + - '3999' + anthropic-ratelimit-requests-reset: + - '2026-01-02T22:10:57Z' + anthropic-ratelimit-tokens-limit: + - '4800000' + anthropic-ratelimit-tokens-remaining: + - '4799000' + anthropic-ratelimit-tokens-reset: + - '2026-01-02T22:10:57Z' + cf-cache-status: + - DYNAMIC + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + x-envoy-upstream-service-time: + - '350' + status: + code: 200 + message: OK +- request: + body: '{"max_tokens": 4096, "messages": [{"role": "user", "content": [{"text": + "What''s the first movie listed on https://rvest.tidyverse.org/articles/starwars.html?", + "type": "text"}]}, {"role": "assistant", "content": [{"text": "I''ll fetch that + page for you.", "type": "text"}, {"type": "server_tool_use", "id": "srvtoolu_01WD9r1pi8iKmUkg946XxKiw", + "name": "web_fetch", "input": {"url": "https://rvest.tidyverse.org/articles/starwars.html"}}, + {"type": "web_fetch_tool_result", "tool_use_id": "srvtoolu_01WD9r1pi8iKmUkg946XxKiw", + "content": {"type": "web_fetch_result", "url": "https://rvest.tidyverse.org/articles/starwars.html", + "retrieved_at": "2026-01-02T21:08:24.211000+00:00", "content": {"type": "document", + "source": {"type": "text", "media_type": "text/plain", "data": "Star Wars films + (static HTML) \u2022 rvest\n\n\n[Skip to content](#container)\n\n\n[rvest](../index.html)\n1.0.5\n\n\n\n\n* + [Get started](../articles/rvest.html)\n* [Reference](../reference/index.html)\n* + Articles\n + [SelectorGadget](../articles/selectorgadget.html)\n + [Star Wars + films (dynamic HTML)](../articles/starwars-dynamic.html)\n + [Star Wars films + (static HTML)](../articles/starwars.html)\n* News\n + ###### Releases\n + + [Version 1.0.0](https://www.tidyverse.org/blog/2021/03/rvest-1-0-0/)\n + [Version + 0.3.0](https://blog.rstudio.com/2015/09/24/rvest-0-3-0/)\n + [Version 0.1.0](https://blog.rstudio.com/2014/11/24/rvest-easy-web-scraping-with-r/)\n + + ---\n + [Changelog](../news/index.html)\n\n![](../logo.png)\n\n# Star Wars + films (static HTML)\n\nSource: [`vignettes/starwars.Rmd`](https://github.com/tidyverse/rvest/blob/main/vignettes/starwars.Rmd)\n\n`starwars.Rmd`\n\nThis + vignette contains some data about the Star Wars films for use in\nrvest examples + and vignettes.\n\n## The Phantom Menace\n\nReleased: 1999-05-19\n\nDirector: + George Lucas\n\nTurmoil has engulfed the Galactic Republic. The taxation of + trade routes\nto outlying star systems is in dispute.\n\nHoping to resolve the + matter with a blockade of deadly battleships, the\ngreedy Trade Federation has + stopped all shipping to the small planet of\nNaboo.\n\nWhile the Congress of + the Republic endlessly debates this alarming chain\nof events, the Supreme Chancellor + has secretly dispatched two Jedi\nKnights, the guardians of peace and justice + in the galaxy, to settle the\nconflict\u2026.\n\n## Attack of the Clones\n\nReleased: + 2002-05-16\n\nDirector: George Lucas\n\nThere is unrest in the Galactic Senate. + Several thousand solar systems\nhave declared their intentions to leave the + Republic.\n\nThis separatist movement, under the leadership of the mysterious + Count\nDooku, has made it difficult for the limited number of Jedi Knights to\nmaintain + peace and order in the galaxy.\n\nSenator Amidala, the former Queen of Naboo, + is returning to the Galactic\nSenate to vote on the critical issue of creating + an ARMY OF THE REPUBLIC\nto assist the overwhelmed Jedi\u2026.\n\n## Revenge + of the Sith\n\nReleased: 2005-05-19\n\nDirector: George Lucas\n\nWar! The Republic + is crumbling under attacks by the ruthless Sith Lord,\nCount Dooku. There are + heroes on both sides. Evil is everywhere.\n\nIn a stunning move, the fiendish + droid leader, General Grievous, has\nswept into the Republic capital and kidnapped + Chancellor Palpatine,\nleader of the Galactic Senate.\n\nAs the Separatist Droid + Army attempts to flee the besieged capital with\ntheir valuable hostage, two + Jedi Knights lead a desperate mission to\nrescue the captive Chancellor\u2026.\n\n## + A New Hope\n\nReleased: 1977-05-25\n\nDirector: George Lucas\n\nIt is a period + of civil war. Rebel spaceships, striking from a hidden\nbase, have won their + first victory against the evil Galactic Empire.\n\nDuring the battle, Rebel + spies managed to steal secret plans to the\nEmpire\u2019s ultimate weapon, the + DEATH STAR, an armored space station with\nenough power to destroy an entire + planet.\n\nPursued by the Empire\u2019s sinister agents, Princess Leia races + home aboard\nher starship, custodian of the stolen plans that can save her people + and\nrestore freedom to the galaxy\u2026.\n\n## The Empire Strikes Back\n\nReleased: + 1980-05-17\n\nDirector: Irvin Kershner\n\nIt is a dark time for the Rebellion. + Although the Death Star has been\ndestroyed, Imperial troops have driven the + Rebel forces from their\nhidden base and pursued them across the galaxy.\n\nEvading + the dreaded Imperial Starfleet, a group of freedom fighters led\nby Luke Skywalker + has established a new secret base on the remote ice\nworld of Hoth.\n\nThe evil + lord Darth Vader, obsessed with finding young Skywalker, has\ndispatched thousands + of remote probes into the far reaches of space\u2026.\n\n## Return of the Jedi\n\nReleased: + 1983-05-25\n\nDirector: Richard Marquand\n\nLuke Skywalker has returned to his + home planet of Tatooine in an attempt\nto rescue his friend Han Solo from the + clutches of the vile gangster\nJabba the Hutt.\n\nLittle does Luke know that + the GALACTIC EMPIRE has secretly begun\nconstruction on a new armored space + station even more powerful than the\nfirst dreaded Death Star.\n\nWhen completed, + this ultimate weapon will spell certain doom for the\nsmall band of rebels struggling + to restore freedom to the galaxy\u2026\n\n## The Force Awakens\n\nReleased: + 2015-12-11\n\nDirector: J. J. Abrams\n\nLuke Skywalker has vanished. In his + absence, the sinister FIRST ORDER\nhas risen from the ashes of the Empire and + will not rest until\nSkywalker, the last Jedi, has been destroyed. With the + support of the\nREPUBLIC, General Leia Organa leads a brave RESISTANCE. She + is desperate\nto find her brother Luke and gain his help in restoring peace + and\njustice to the galaxy. Leia has sent her most daring pilot on a secret\nmission + to Jakku, where an old ally has discovered a clue to Luke\u2019s\nwhereabouts\u2026.\n\n## + On this page\n\nDeveloped by [Hadley Wickham](https://hadley.nz), [![Posit](https://www.tidyverse.org/posit-logo.svg)](https://www.posit.co).\n\nSite + built with [pkgdown](https://pkgdown.r-lib.org/) 2.1.3."}, "title": "Star Wars + films (static HTML)"}}}, {"text": "The first movie listed on that page is **The + Phantom Menace**, released on 1999-05-19 and directed by George Lucas.", "type": + "text"}]}, {"role": "user", "content": [{"text": "Who directed it?", "type": + "text", "cache_control": {"type": "ephemeral", "ttl": "5m"}}]}], "model": "claude-haiku-4-5-20251001", + "stream": true, "tools": [{"name": "web_fetch", "type": "web_fetch_20250910"}]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '6381' + Content-Type: + - application/json + Host: + - api.anthropic.com + X-Stainless-Async: + - 'false' + anthropic-beta: + - web-fetch-2025-09-10 + anthropic-version: + - '2023-06-01' + x-stainless-read-timeout: + - '600' + x-stainless-timeout: + - NOT_GIVEN + method: POST + uri: https://api.anthropic.com/v1/messages + response: + body: + string: 'event: message_start + + data: {"type":"message_start","message":{"model":"claude-haiku-4-5-20251001","id":"msg_019p4i4fiXrPj1EiQZaRjyzK","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":2714,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} } + + + event: content_block_start + + data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} } + + + event: content_block_delta + + data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"According"} } + + + event: content_block_delta + + data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" + to the page"} } + + + event: ping + + data: {"type": "ping"} + + + event: content_block_delta + + data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":", + **"} } + + + event: content_block_delta + + data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"The + Phantom Menace** was"} } + + + event: content_block_delta + + data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" + directed by **"} } + + + event: content_block_delta + + data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"George + Lucas**."} } + + + event: content_block_stop + + data: {"type":"content_block_stop","index":0 } + + + event: message_delta + + data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":2714,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":23} } + + + event: message_stop + + data: {"type":"message_stop" } + + + ' + headers: + CF-RAY: + - 9b7d96f3ae83e655-DEN + Cache-Control: + - no-cache + Connection: + - keep-alive + Content-Type: + - text/event-stream; charset=utf-8 + Date: + - Fri, 02 Jan 2026 22:11:00 GMT + Server: + - cloudflare + Transfer-Encoding: + - chunked + X-Robots-Tag: + - none + anthropic-ratelimit-input-tokens-limit: + - '4000000' + anthropic-ratelimit-input-tokens-remaining: + - '3999000' + anthropic-ratelimit-input-tokens-reset: + - '2026-01-02T22:10:59Z' + anthropic-ratelimit-output-tokens-limit: + - '800000' + anthropic-ratelimit-output-tokens-remaining: + - '800000' + anthropic-ratelimit-output-tokens-reset: + - '2026-01-02T22:10:59Z' + anthropic-ratelimit-requests-limit: + - '4000' + anthropic-ratelimit-requests-remaining: + - '3999' + anthropic-ratelimit-requests-reset: + - '2026-01-02T22:10:59Z' + anthropic-ratelimit-tokens-limit: + - '4800000' + anthropic-ratelimit-tokens-remaining: + - '4799000' + anthropic-ratelimit-tokens-reset: + - '2026-01-02T22:10:59Z' + cf-cache-status: + - DYNAMIC + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + x-envoy-upstream-service-time: + - '639' + status: + code: 200 + message: OK +version: 1 diff --git a/tests/_vcr/test_provider_anthropic/test_anthropic_web_search.yaml b/tests/_vcr/test_provider_anthropic/test_anthropic_web_search.yaml new file mode 100644 index 00000000..596fb850 --- /dev/null +++ b/tests/_vcr/test_provider_anthropic/test_anthropic_web_search.yaml @@ -0,0 +1,287 @@ +interactions: +- request: + body: '{"max_tokens": 4096, "messages": [{"role": "user", "content": [{"text": + "When was ggplot2 1.0.0 released to CRAN? Answer in YYYY-MM-DD format.", "type": + "text", "cache_control": {"type": "ephemeral", "ttl": "5m"}}]}], "model": "claude-haiku-4-5-20251001", + "stream": true, "system": [{"type": "text", "text": "[empty string]", "cache_control": + {"type": "ephemeral", "ttl": "5m"}}], "tools": [{"name": "web_search", "type": + "web_search_20250305"}]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '413' + Content-Type: + - application/json + Host: + - api.anthropic.com + X-Stainless-Async: + - 'false' + anthropic-version: + - '2023-06-01' + x-stainless-read-timeout: + - '600' + x-stainless-timeout: + - NOT_GIVEN + method: POST + uri: https://api.anthropic.com/v1/messages + response: + body: + string: "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-haiku-4-5-20251001\",\"id\":\"msg_01RvJ82gtJk26N8QKyeQ2cBe\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"usage\":{\"input_tokens\":2247,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"cache_creation\":{\"ephemeral_5m_input_tokens\":0,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":26,\"service_tier\":\"standard\"}} + \ }\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"server_tool_use\",\"id\":\"srvtoolu_019vghbahbRKPzBwadunDFSW\",\"name\":\"web_search\",\"input\":{}} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"query\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\": + \\\"ggpl\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"ot2 + 1.0.0 \"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"CRAN\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\" + release da\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"te\\\"}\"} + \ }\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0 + }\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"web_search_tool_result\",\"tool_use_id\":\"srvtoolu_019vghbahbRKPzBwadunDFSW\",\"content\":[{\"type\":\"web_search_result\",\"title\":\"CRAN: + Package ggplot2\",\"url\":\"https://cran.r-project.org/package=ggplot2\",\"encrypted_content\":\"Eo4DCioICxgCIiQ1MzY3Y2M0OC03OTYwLTQ5NmUtOTkyYS1kYmExZTRkMDViNDISDLp+3eWM+kcn3Szl4hoMiek2907qkVbe3bpfIjBn9AYkji4oT7kVBCEyd25CcFLnPj0OaJwMmrEFKvz6cbozX0jrSozBgd2sA9i/wqcqkQJsZ064CjT1PDVT40P6lAK0Pn1if2QhIPFtivkuEc7qn9fQCF6nPhL0cR1JT+YgBB5ArtY5+wFjgMn6WdO0D0N+/rXE9Nks1l8nQX7UQW3VkG4iko8pNVleE8d01uK6wuNXPBefpW/9hn5aBkBwDHuR94ZnuB1umx4RVJ1fLhp8quMJDImyYvA7SfpLeRlKvdzTEdtwj61aDs23IcfRD9TWtqMc9GtMDD8z695huJQxFRGmjW+VkWzDJsZxVnBIuv56r76z+G7RzxlTYQlBBk+Rum7/fCBuY2UqCNielIBn+EZCVnouhIZ2XV+ycL+ELL4pFBfWVbfcY32aommCU8iV1gQhw+twY1o6cDFzwPII4JcYAw==\",\"page_age\":\"November + 14, 2025\"},{\"type\":\"web_search_result\",\"title\":\"Changelog \u2022 ggplot2\",\"url\":\"https://ggplot2.tidyverse.org/news/index.html\",\"encrypted_content\":\"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\",\"page_age\":null},{\"type\":\"web_search_result\",\"title\":\"ggplot2 + - Wikipedia\",\"url\":\"https://en.wikipedia.org/wiki/Ggplot2\",\"encrypted_content\":\"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\",\"page_age\":\"4 + days ago\"},{\"type\":\"web_search_result\",\"title\":\"Releases \xB7 tidyverse/ggplot2\",\"url\":\"https://github.com/tidyverse/ggplot2/releases\",\"encrypted_content\":\"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\",\"page_age\":null},{\"type\":\"web_search_result\",\"title\":\"Releases + \xB7 cran/ggplot2\",\"url\":\"https://github.com/cran/ggplot2/releases\",\"encrypted_content\":\"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\",\"page_age\":null},{\"type\":\"web_search_result\",\"title\":\"ggplot2 + R Package Stats, Author, Search and Tutorials | Examples | Downloads | Statistics + | Citations\",\"url\":\"https://rpkg.net/package/ggplot2\",\"encrypted_content\":\"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\",\"page_age\":null},{\"type\":\"web_search_result\",\"title\":\"New + version of ggplot2, new problems \xB7 Issue #255 \xB7 pbiecek/archivist\",\"url\":\"https://github.com/pbiecek/archivist/issues/255\",\"encrypted_content\":\"Ev4KCioICxgCIiQ1MzY3Y2M0OC03OTYwLTQ5NmUtOTkyYS1kYmExZTRkMDViNDISDCiaHqRLxllrMJkz3hoMSDqKwGzjUoXzKzl1IjCoQuAIoZrVNVhpuKjQXTEkb93hWnb4kwCDM/426xVoxK6BpBrZRdU0mHEFJ74wzjMqgQr/vM7kYGFtCQU3IihuFDQ2VaFOYiH1+tlZ6FqL/qkm9hKkHrl+qbNiSZdOp2zNgAb8P3Fu9YNz6LRlgd4flFx2rIYIWKT5L+BzDcxnzQk3vLO4Kd9vlSEOCcaKc6InqQBAHAWlAmN6Y80W9pq9qsHZQAp6JOeglVezXPJ6NG3il0Ylt/N4krMlzCB+KlybzUVF01jw/qGHpasEvcRbE9UHVMqbWSnn//EPO2A432bd7K5JWouMoTlAMHEyLxmoRzPfdjcTc50zT/UpJMgysO2Heobcm4AskLl9qL99jxCIQgx3aTwVWj1k7dQvQsf5ELMty36tou1F+16Clqdr9o6X11Z7N7SRCi6srdDn1wXGA8dJ/DfirhBETZFLGCIT+wxTKDurMOanNHinkViVxoB8nBJbkpfSNF9PwDbKSUaJ5bQDT4VVXuiPCrrhQ+qzqPpN3nY9+vn7AGeuGWURhYoFnUFJFpe2q7MmxmqQT6L2xlLpobH1//kegCnn/gVtDBxng9OKrXSpJj4/HIbDDRXM07McUDcZmm0/UGRaDPQtss2hPgB2hI0rqm9CnKCT/3xjl1/QXzNyXOWkmMyIHjJHxVF0VaoO+YSC+0XiXJErUZG9S9RTJU1zSQ52G5cwQ4Lax8mTb6JMob52Uxjj/rK0xY31y3QwXvon08IpLPBN8IyxbuzWc/iZCPHAISZCGGOS3ZxQrUcEoyv468GY82YM3szpVLXXElV+2E8slfsy/85ek1V0jBaVkhLlSLkB9EntFWAThHJkFFU/paOaTIsR3+ccN63oZmYmmcSIfmHaZgwmzjnNAl+teAfJEILVAuQafu5BALtG9dITzkm78W5A8olL6gGUKfTdHsfHZ6WMnXNjzZd1nO2tAxY4Ti2zDLJfCMnX5WhImYgO+Dbeoaj/xml7naohc9VELeed/yjsW34P8LHJiXcok8Ip/TJxKWO0qWQpDGcRD6ApmQm52DJOLYHN50UGItAPtvqCLc4jumbG9WvYN14cKa8thEhU26qyldupCTgT4Etn85OJEBOE0hTYx0Klx47y/8xrDaN7hofuRcwprRXa9aXSITaXjgbyCuooSVca1qOxGI5uuRN8p2E9n6Wahy4HuwuKAtknoAHJFl95u/bifQk+t2NeWm+QwTld1Frui2TufGN+UrnqG3NGAbHmnEV0n6Jc3EYGyRnHYeHixh6jUeqbf/6BF/gcJkdjX+aWZAMyeVmNi6YqkbtADNhwB2u/VdGYEG8Cf2tuvo5qt9kvNalS94RrD1cN4zfbvk8EZ7bWQGTYFCCCgvYIqw0nexpd2+IK1ymHMV0gfA16r4ibCu2RCuxJJeHvVjp2d7ETqeg5tRR3a4Ecr7/HIGH3qrkfQAi9PLQA7/qFFr9X9aYLnMToza//ER4JVCYVv2CCrs45Dbk0x77ZFtAgv0haJU/twaWzu4tch/3P8igeKBrYxFkoejNNtsYlVKqoskk4Tnm5DnvV5DC+LjiDZpgo7+3+Qh32neEmiUdpJi9PWUVrzp8/l5Twke8XHODsQQcCp9vhmgejE9quqKWV9Jb5zbkkyccxrR5pD2ue/2kmel73K3xwSaI+NYZEq8OmDNe0JBBBnEROkkjtabOJVeh1CgkIBqFaEgDBCpS5SOHCO+Z+n28C3AiHPFApuBCKY7Vb4G9Ql9MrtZ4WvCQZlJc2AuuNwQ4t54KaTNcYAw==\",\"page_age\":null},{\"type\":\"web_search_result\",\"title\":\"Package + 'ggplot2'\",\"url\":\"https://cran.r-project.org/web/packages/ggplot2/ggplot2.pdf\",\"encrypted_content\":\"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\",\"page_age\":null},{\"type\":\"web_search_result\",\"title\":\"NEWS\",\"url\":\"https://cran.r-project.org/web/packages/ggplot2/news/news.html\",\"encrypted_content\":\"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\",\"page_age\":null},{\"type\":\"web_search_result\",\"title\":\"ggpubr: + 'ggplot2' Based Publication Ready Plots - CRAN\",\"url\":\"https://cran.r-project.org/package=ggpubr\",\"encrypted_content\":\"EocKCioICxgCIiQ1MzY3Y2M0OC03OTYwLTQ5NmUtOTkyYS1kYmExZTRkMDViNDISDOkIDZBmEkdkY/ku9hoMgAwxHoCa/5fnY+IPIjD6RCpbsfnCMZsBD7eRZY94juwK0umyC97J959tC9DVYSTkf/a0ISyP/xcfuZzFIX8qigli00/DURjFhLLgUyA1w1cJ5/EVP/UFkZU12WCAYRKV0frD7VPLrzN4gWBYGwGsGOcS984aU16D5JSOgIOOXt3SPABtw2h7fw1FujDCg6pnr8juekw5I4SikzCeLEpigWg+vmc4zfZffsJuoBQaD6jxObaMJhTybDTjWKmMdTz3Eq97FLllTgCXAsErNGokfTY/yxJAo9DxZcZYuMl489OG5ThmbZLe1aQeAZVr3YFfS+XMa+0L885oCoel+S0WIAEOW3xXuzIw9tq+oMKxZvAdYA7usK1WihBWPl/ayTIOuvzL7XFX6SnuSNT7QDgfelRAfl434aSVdr+Y27WitoRNmODJov3zLGjP06pE5cPdeB9Bsvzb6YsHPvSx3FxfBH2+fx2kuCd10HeDo39cpVfYK5zBrbqPUKbECGuv0LajYVT1G7h4PBDyjWEMQJ3SHZCsxJSI+D2V9vDxPDZ5/oLy+zq7TXIkBskDW13JD2pfdRdztXboffddHqE3jIQH/byodnyV/+FPSwVrTaYxwBO7A2dMC/vFpKe1rD5AWdoCbzgqVNgJFjLLEiffSXIIfItrKNf7IwnjMLCVaBaZ7PVJ7Mk5ZiymrhooXB+DHUZabgbjgRFSe0TKju26ZeH+5qw7NLWfIFaWW6ZdfZthayNnIvPhVbdo9gHlb0vtHtLIzo/tV4k2/DV0Efvo8nGLoZ3bRRH3/oeHqGtQB99bTfHLq+1HN2UVsLXlQGDMF0W5b079aoUoCmSM5A8RSdLaovgpzTYjgeutLP7M9KOn9LR0+BTNAj1iDGpRUnKqMqQ1j78aKQmqNs7X64nVT5jOzSaZSwgWyRxTrLz/kcKX2ZUOOH1LjHgfwfbh8OMbGLCkBPOkGoUjhs96qtUN+M9eVK4s9GMDGHNvSFEtlDIfIzo9F9YxM6rPL7cBMIeDBKM1XUsOaueZdgznduuVi89l2EmfPCO8nfxMOgjILjwakdMG6Pvdwm+I2jyH1jOkUrD0z0ihHVSsVVGXWoUvO1yTldIrgVZoSGlZnF8HcmJZ8hqGYhFt78hCOrokBhWU64140ERmowwM1acKif9CBsocpRGHmNdaF8TtOp5Of74fkb3MqLhpLzmK6eCItOl2R1DiDniTMPDvpQXGF7t6RLVFAhj1WM0ZaS2v5sqF3gp1Vjc66rx9lTxPKfsEpTc+XBZ7QtWZ+14G8/TgUOzMVuc7R/y9iZcSchbalagerhaGypAhA8ZJ77UYEi5dMzE5ij8cN8KBIxEDEmG8UUrU+85C2nsXstpVGS27R88vgcR/nhD/ngU6Y0CFd28GogEANt+wpnP5tgf37SJpDDmZCKGOwkHYE16mxsLXWLSOsnuLZTFK4BqN4U9Sjg8Nt+qlFPFnJsn99MpNlGPMObThGAJ5GIu23CsqDcofpmU1SPJivJSQY+NPCh6XmLZElCvBg9DIi7IHCW3c2A0r54n/vdJ/73MoODyk6pfDT6SOsgPVUiFv8FBH8o79eFZE21pfuhiQSxkMr4T/QIs/3LIpuOjYddTSqLs2FaQQJIxVGAM=\",\"page_age\":\"October + 17, 2025\"}]} }\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1 + \ }\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":2,\"content_block\":{\"citations\":[],\"type\":\"text\",\"text\":\"\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"citations_delta\",\"citation\":{\"type\":\"web_search_result_location\",\"cited_text\":\"... + 0.5.1 (2007-06-10 21:49), 0.5.2 ... (2012-09-04 08:16), 0.9.3.1 (2013-03-02 + 15:57), 0.9.3 (2012-12-05 13:11), 1.0.0 (2014-05-21 15:36), 1.0.1 (201...\",\"url\":\"https://rpkg.net/package/ggplot2\",\"title\":\"ggplot2 + R Package Stats, Author, Search and Tutorials | Examples | Downloads | Statistics + | Citations\",\"encrypted_index\":\"Eo8BCioICxgCIiQ1MzY3Y2M0OC03OTYwLTQ5NmUtOTkyYS1kYmExZTRkMDViNDISDBlfY+aB42lx7utL+RoMEXnx0nKjWPvIF3ubIjAS1J+BAkO6BISItYPl35fG04hc7uYO/sKAKtK2rQBix9PM8pk8WhootU0m+gXYDd8qE2Roa5kQDGmdemSY5/GcKiEC6kgYBA==\"}} + }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"text_delta\",\"text\":\"ggplot\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"text_delta\",\"text\":\"2 + 1\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"text_delta\",\"text\":\".0\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"text_delta\",\"text\":\".0 + was\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"text_delta\",\"text\":\" + released on 2014\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"text_delta\",\"text\":\"-05\"}}\n\nevent: + content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"text_delta\",\"text\":\"-21\"} + \ }\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":2}\n\nevent: + content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":3,\"content_block\":{\"type\":\"text\",\"text\":\"\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":3,\"delta\":{\"type\":\"text_delta\",\"text\":\".\"} + \ }\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":3 + \ }\n\nevent: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\",\"stop_sequence\":null},\"usage\":{\"input_tokens\":2254,\"cache_creation_input_tokens\":17269,\"cache_read_input_tokens\":0,\"output_tokens\":110,\"server_tool_use\":{\"web_search_requests\":1}} + \ }\n\nevent: message_stop\ndata: {\"type\":\"message_stop\" }\n\n" + headers: + CF-RAY: + - 9b7d96fb2803e74d-DEN + Cache-Control: + - no-cache + Connection: + - keep-alive + Content-Type: + - text/event-stream; charset=utf-8 + Date: + - Fri, 02 Jan 2026 22:11:01 GMT + Server: + - cloudflare + Transfer-Encoding: + - chunked + X-Robots-Tag: + - none + anthropic-ratelimit-input-tokens-limit: + - '4000000' + anthropic-ratelimit-input-tokens-remaining: + - '3999000' + anthropic-ratelimit-input-tokens-reset: + - '2026-01-02T22:11:01Z' + anthropic-ratelimit-output-tokens-limit: + - '800000' + anthropic-ratelimit-output-tokens-remaining: + - '800000' + anthropic-ratelimit-output-tokens-reset: + - '2026-01-02T22:11:01Z' + anthropic-ratelimit-requests-limit: + - '4000' + anthropic-ratelimit-requests-remaining: + - '3999' + anthropic-ratelimit-requests-reset: + - '2026-01-02T22:11:01Z' + anthropic-ratelimit-tokens-limit: + - '4800000' + anthropic-ratelimit-tokens-remaining: + - '4799000' + anthropic-ratelimit-tokens-reset: + - '2026-01-02T22:11:01Z' + cf-cache-status: + - DYNAMIC + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + x-envoy-upstream-service-time: + - '751' + status: + code: 200 + message: OK +- request: + body: '{"max_tokens": 4096, "messages": [{"role": "user", "content": [{"text": + "When was ggplot2 1.0.0 released to CRAN? Answer in YYYY-MM-DD format.", "type": + "text"}]}, {"role": "assistant", "content": [{"type": "server_tool_use", "id": + "srvtoolu_019vghbahbRKPzBwadunDFSW", "name": "web_search", "input": {"query": + "ggplot2 1.0.0 CRAN release date"}}, {"content": [{"encrypted_content": "Eo4DCioICxgCIiQ1MzY3Y2M0OC03OTYwLTQ5NmUtOTkyYS1kYmExZTRkMDViNDISDLp+3eWM+kcn3Szl4hoMiek2907qkVbe3bpfIjBn9AYkji4oT7kVBCEyd25CcFLnPj0OaJwMmrEFKvz6cbozX0jrSozBgd2sA9i/wqcqkQJsZ064CjT1PDVT40P6lAK0Pn1if2QhIPFtivkuEc7qn9fQCF6nPhL0cR1JT+YgBB5ArtY5+wFjgMn6WdO0D0N+/rXE9Nks1l8nQX7UQW3VkG4iko8pNVleE8d01uK6wuNXPBefpW/9hn5aBkBwDHuR94ZnuB1umx4RVJ1fLhp8quMJDImyYvA7SfpLeRlKvdzTEdtwj61aDs23IcfRD9TWtqMc9GtMDD8z695huJQxFRGmjW+VkWzDJsZxVnBIuv56r76z+G7RzxlTYQlBBk+Rum7/fCBuY2UqCNielIBn+EZCVnouhIZ2XV+ycL+ELL4pFBfWVbfcY32aommCU8iV1gQhw+twY1o6cDFzwPII4JcYAw==", + "page_age": "November 14, 2025", "title": "CRAN: Package ggplot2", "type": "web_search_result", + "url": "https://cran.r-project.org/package=ggplot2"}, {"encrypted_content": + "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", + "page_age": null, "title": "Changelog \u2022 ggplot2", "type": "web_search_result", + "url": "https://ggplot2.tidyverse.org/news/index.html"}, {"encrypted_content": + "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", + "page_age": "4 days ago", "title": "ggplot2 - Wikipedia", "type": "web_search_result", + "url": "https://en.wikipedia.org/wiki/Ggplot2"}, {"encrypted_content": "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", + "page_age": null, "title": "Releases \u00b7 tidyverse/ggplot2", "type": "web_search_result", + "url": "https://github.com/tidyverse/ggplot2/releases"}, {"encrypted_content": + "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", + "page_age": null, "title": "Releases \u00b7 cran/ggplot2", "type": "web_search_result", + "url": "https://github.com/cran/ggplot2/releases"}, {"encrypted_content": "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", + "page_age": null, "title": "ggplot2 R Package Stats, Author, Search and Tutorials + | Examples | Downloads | Statistics | Citations", "type": "web_search_result", + "url": "https://rpkg.net/package/ggplot2"}, {"encrypted_content": "Ev4KCioICxgCIiQ1MzY3Y2M0OC03OTYwLTQ5NmUtOTkyYS1kYmExZTRkMDViNDISDCiaHqRLxllrMJkz3hoMSDqKwGzjUoXzKzl1IjCoQuAIoZrVNVhpuKjQXTEkb93hWnb4kwCDM/426xVoxK6BpBrZRdU0mHEFJ74wzjMqgQr/vM7kYGFtCQU3IihuFDQ2VaFOYiH1+tlZ6FqL/qkm9hKkHrl+qbNiSZdOp2zNgAb8P3Fu9YNz6LRlgd4flFx2rIYIWKT5L+BzDcxnzQk3vLO4Kd9vlSEOCcaKc6InqQBAHAWlAmN6Y80W9pq9qsHZQAp6JOeglVezXPJ6NG3il0Ylt/N4krMlzCB+KlybzUVF01jw/qGHpasEvcRbE9UHVMqbWSnn//EPO2A432bd7K5JWouMoTlAMHEyLxmoRzPfdjcTc50zT/UpJMgysO2Heobcm4AskLl9qL99jxCIQgx3aTwVWj1k7dQvQsf5ELMty36tou1F+16Clqdr9o6X11Z7N7SRCi6srdDn1wXGA8dJ/DfirhBETZFLGCIT+wxTKDurMOanNHinkViVxoB8nBJbkpfSNF9PwDbKSUaJ5bQDT4VVXuiPCrrhQ+qzqPpN3nY9+vn7AGeuGWURhYoFnUFJFpe2q7MmxmqQT6L2xlLpobH1//kegCnn/gVtDBxng9OKrXSpJj4/HIbDDRXM07McUDcZmm0/UGRaDPQtss2hPgB2hI0rqm9CnKCT/3xjl1/QXzNyXOWkmMyIHjJHxVF0VaoO+YSC+0XiXJErUZG9S9RTJU1zSQ52G5cwQ4Lax8mTb6JMob52Uxjj/rK0xY31y3QwXvon08IpLPBN8IyxbuzWc/iZCPHAISZCGGOS3ZxQrUcEoyv468GY82YM3szpVLXXElV+2E8slfsy/85ek1V0jBaVkhLlSLkB9EntFWAThHJkFFU/paOaTIsR3+ccN63oZmYmmcSIfmHaZgwmzjnNAl+teAfJEILVAuQafu5BALtG9dITzkm78W5A8olL6gGUKfTdHsfHZ6WMnXNjzZd1nO2tAxY4Ti2zDLJfCMnX5WhImYgO+Dbeoaj/xml7naohc9VELeed/yjsW34P8LHJiXcok8Ip/TJxKWO0qWQpDGcRD6ApmQm52DJOLYHN50UGItAPtvqCLc4jumbG9WvYN14cKa8thEhU26qyldupCTgT4Etn85OJEBOE0hTYx0Klx47y/8xrDaN7hofuRcwprRXa9aXSITaXjgbyCuooSVca1qOxGI5uuRN8p2E9n6Wahy4HuwuKAtknoAHJFl95u/bifQk+t2NeWm+QwTld1Frui2TufGN+UrnqG3NGAbHmnEV0n6Jc3EYGyRnHYeHixh6jUeqbf/6BF/gcJkdjX+aWZAMyeVmNi6YqkbtADNhwB2u/VdGYEG8Cf2tuvo5qt9kvNalS94RrD1cN4zfbvk8EZ7bWQGTYFCCCgvYIqw0nexpd2+IK1ymHMV0gfA16r4ibCu2RCuxJJeHvVjp2d7ETqeg5tRR3a4Ecr7/HIGH3qrkfQAi9PLQA7/qFFr9X9aYLnMToza//ER4JVCYVv2CCrs45Dbk0x77ZFtAgv0haJU/twaWzu4tch/3P8igeKBrYxFkoejNNtsYlVKqoskk4Tnm5DnvV5DC+LjiDZpgo7+3+Qh32neEmiUdpJi9PWUVrzp8/l5Twke8XHODsQQcCp9vhmgejE9quqKWV9Jb5zbkkyccxrR5pD2ue/2kmel73K3xwSaI+NYZEq8OmDNe0JBBBnEROkkjtabOJVeh1CgkIBqFaEgDBCpS5SOHCO+Z+n28C3AiHPFApuBCKY7Vb4G9Ql9MrtZ4WvCQZlJc2AuuNwQ4t54KaTNcYAw==", + "page_age": null, "title": "New version of ggplot2, new problems \u00b7 Issue + #255 \u00b7 pbiecek/archivist", "type": "web_search_result", "url": "https://github.com/pbiecek/archivist/issues/255"}, + {"encrypted_content": "EvsjCioICxgCIiQ1MzY3Y2M0OC03OTYwLTQ5NmUtOTkyYS1kYmExZTRkMDViNDISDCogQG34UQSo2VD4IxoMoirRdUspWV6QzsplIjD7D7jpqlnpXy2K1W3nFgYcm/kv73TYTCemG4BUH8dGxiFEa9kFKDGypBYvFnAfhB8q/iLziMrWnLrP3lRw5+0RKj4JSI1tL+m3O+sN5n67mFSmn8F4DrYy+AvfN2vW42MFOVTMDKyuPvvs16Qatnx7nGy1j0cb53LgNQ5IGGAV+MZMSYnVvF3Wr63G5dlt2WHBFIoski1u3mPf6Y2dDXwODci+qv6svDs6tatpynBOnZeKevwiGpR5bATRyIL6KuY7S0BnrNauV5q88iYXus0Zsk5MSqdF/RP01P6Kvii81waRcWGO5MH+an+nB7Ycxjzd+bSKU0jSLjp1lHWU3wzMrZRDt7pO3AuA1YGzLXLK6IhlPYCNljVzxd4FIkDeroC1aB9cw1sqTY0HnaOjU9BJLUCpQ7dmZMqpmWJ8aFmymFrP104ZoWCNb3tWhP89GgTaM2e+XKBcG3jMZJr6ewGXUn6v25PbQ6UNiIli5kFhbK+797SpQpcRgOw99bF+aRheI4wCtpjoWb/VkEOd9dVPqmeu+s+etW4JLQwOpl82IapWB7Pk+J2nkYR/9X6nCPd1h07XDTNE9pnijdu3cPFiSyrh8SoaLkDc3oI0hs8/KA5ANxJioVrPvfDgU9vNEjB/BeL5jkw31/ivhUWd6xeBrZUkmRCF28kYywPrIcHzPJ4NGEfXkeK62LLApvMMWXQbpgfGAWLgVzlqMYlAwimjYvBp6icUrhJ/ePOvxYPrvVMjcNV0qScozEyj+spplSfvbRhw9fluBEUGIxYH14X/F8bGQRwMHPRloCVs0f2UnAiO4XEYtySucd9kSZGkdo200QudLvX7OLQqRDlBw6UmjXFecANI2Y7mP2Cf5/UgO8BfNREgFBqwA4huZU4WSu2koroYYgp592Vk6mi+x97hr1ObO/LvQjONh5iGBmmyrrpGI59PPkY31SvcQyuLETTMng4xc7KE7TPWcwkE8N8XtjD5x7cWaM3FXAiglrJsfjDejMigJncr18bil7Q13SuN8M3sw7okGB9mSMi6/vNHJaLt09z5mbd9Syn37rRRrTEo7EEGygKoEYoHeniv3rNEEMvpZjKfj8ZxRSVS2WfD+4mA91awuBoiiqdZIO7r4LF4KFD5bkfY+w24u2CqsD8ka1BdmmftHzBejabBtUNtOEeeB3AUmWsrcBddWS8YOeZTu9OstBp4H4BYyRiPTOluaOqVXoMfAoEkepKcQ05IMSxlZkFSsQ9+33PO21rfTZC9j6dljcikuIQ3ExJs4/+d8dDh6gk2lgub2B1Sr6L2/faLIM4jjCbIDy2zQgzTiyCqqcs85h3qHQ/m6Sl33+2aHKVpU9erYO5eD0o5jMDgF4c7sd/KQzNc7FyhujylmoTeqLPNN42DMTmFWrg21GLZn1pOxoGaOqAMDk5YX9/1Z1MoQjO02QWsMKUrfUHWm3Ikp6yagXGa40jyuUuDAOJFDdTbTyS7DslWsiHVkb0QLsYFYkU/2QtOZNteM/nuQ9mwyhnhXqwQOCik+Lb4xhcsiXlQ0zdGa5Vv79dwKInBpb8rY/1HAiEReQfn27We/NWn+7nJuGZigvc4PzHYOsZFPhkoOsrEAmeF5QkA551BV0S9sIlfOWKNk6tXUPa+k6jvAi/q6RFsJwC7C0HYDDmHdGQofGvWj/5w2ncpXGw2dBNt64rw7KLn2zR0lTDzB6il+MnsRYRMNXHOIWxL14VBKl6QUDE7Sm1CyUT5qbhXD4Z7MukuODt9wwpin2Gd1U4ue9l5Iq8W6lliEusmx4AF7SULI9mfJR8CWz/4ArXwMPMTAEPiHVMTfopex9W773/zKtugTnyMGKtwxLIv8McPV25PCxPNN6yYMNJHUZV/lJ5PDpuY9fTqfPXPzIhklaa40eqn0LfYjlk/PBimdJMVz6ffBmWk20CBaI3tDj9A08cfRot469a/BR0FIYD80O/Cb7FLANF/CcInPjjjx3XuNtxd7SIOmRuxuOBJqZCTaB0C0pe2x7KCFMfAxx5bQTvHoUf9YJ1XckJZRfo2ljFq5RL8jqgNlZJx4XPRJTRESDnCDLxyE8toeekCpop3/rCQ0o2IQClKYxUHF3wlz3Q2n3NTyCv1f/Uq6H4N03V9rTusfHWZooVXsLYi+y3cXHSMH3zSI+wvp0fdiTnewh3GbXqJ1bVfQwEarI/4AOgoQd7jEh5oGYi5p8/OtIIhlAN/qHAaQZN2Ze6AphcJjw3vXCWAge67nKYtv12alorlCEncoAXlCzUNoJoBaB+fasT/jBINx1pR533j/sP2sLYpGBzQ95wo+zrjBMuqc8NDxFlJMaNFKEEzwb5IEdmLHic85rNp/UnUY7H1Xj8fzmavewvUxQb9iCy/TeuQe6L5BVvspRLJrjX6FR9/6nIHOTQ4aAAMBOUUL2nvnjoiNSP7lqMZNP+nIDLo4lAmsngiesuZHj9/Br1gYW+yUen2RcBiCV2XnF/AujYIR8nj8a9sXfxeLnOl263RU25isLnKSuLO2taNT9yIa8GTiEdCnCow9h2WrMhuqM3R8i0K3bqLni/4YXf/X9ORLVr69KrkyeqhlWR2PwpcKRPU/j5M9781QKt8LQpZvMk+zSvjj4VmGEG+wZlfFiNa2rQmneU05Aniyrl/1N/hcJVjbiV5Pru1uayG5yB14OwF2bHSkx+T+rNeuQVQClVbvrZKjsGNEcBVtafki+4dHDr5fvw4ygPLkMEfjBzBIHUmGcbARXjdhryoA6Z4CH50ROpptklteV8R9SB385TuE98Se21B+2kkG3xqUrecwWNqklilTeHNp6qF06apwMVCXMTr1EXKEJX0D9nsxd40dvyGbFyYjvbYSTOlk2PSDNReCZ3APEO1q9eHZqwtNeP8TxlbDTWYayufW4kvC5Aaeb7dau4a1BTxXI47QY9IyQP2DWIxBlunEfixDyfRImXRqhZE0K5DUAOqj6q2FYHv79UucHNlqJQlC+m+Hfz4lYu6oATYwiczY05vStZB56bvq7VGYY0/z8F2r5N+MmR36oqdlSzDIJkhQPgd4HpPNwv2FgkCBkcMcfGR4IHegvxMCTgoMedyiwV5uELJIOibqI4x5iBdWdRgYgy7dByKRXfyUcoC9penWYjbund9T7ThXnGWDbMlGPX7oC9nz1PDVrAytq9ubQDAHBKQ03e0cB3C+DweL2aB3vQpDZkLk8qwkxDYcXKJO9Gcw6eG4tUYRKHzmqarDXtHn+rhF0Js61kFRqqCfZn34Ktb4FNtCZFKjgqzMrMcwabi18uuM7q9e/svU0sII/tnl7WbqVKvobSt4jOu32Enb6IoRbn7lacuV8cUfi/XAJuo2clZ+ZzxN/B4QV4FxYzYLI55P0gr1bFDGlwlEc5jitImFhBrNHZsVz/iNkVscds+2gMb+PuYOIs23Ygv8yhJj1A8c9cmValILvQY8MPPu1MU5UfpEQBBVQUvRFSNF8Y90cKlKRVcTFK7akEV/QtTsSIGP7oODTF+LNV6C4qRxAmcMDH7diBzyj4/4ZmbZoopHqwF53guIwI+2m/xnUc9lIqGfck7uK5kaxsaFSqIcfEQuLMKhmYNqD2NiAmO5W/Jm5T6F4lXzEbLWWgTG+8JH4o7S6UJzDeWsS4DmTPmr3fj15eo0ioVj9Wi3XuQtH8chGVmkqZ2giFCJbnP9JNuNOR+iUjIlZs4XAPqKBTJC2pWDamelDXC56eWcPAIcqTFPyNkiP0kmPjpknTMXQK3HYSr42JJRWLX8ak/N5e5VdetsJY5okbQy279BSIdoV92rVRUoUJDXozL++pZS4sxUeXtGyivOeDeZjxGwIZtHQECEMJ/MumXTa77FJvh6jtdeDQmGu3+/7yVWv/GzdL4RsvqFLLBKW4dquvBtC/mEKVfeINm1Vnlg4qKNGlGJtE7/WXHhqb3wzty5qhZX1ODYcs8W+NWa/Xyt0bmHFM4iplEPuamlGvo8jJDKSNpUi+otGihSqWpwkJo/5thG6Jij65gZR3nh7A6Ypex+6GRNmLvk5hs+A24NeSr5G7JVzO3U5Nxatz+sFL4r4Yi0scVj2TCAtVcn15JwLNN54eG1rP0p+pVJ4XHtfUhH6dIL7EdXvHniLc7B+easPFFHnUq5WAITu0RJaZubZuPBh3EtAaJknT5SLd+kx/iLu0JHOKOnzNHXfbgIwzyEgsnl8Ryf8u3P2wOgpW3usBuyuoXbZ5HHiLsOeboVW6v0evhMCLhCYlFnc305ojG1Z5xbUCNbdOmTAGTHK6J5u8IbaH+RKVW5w3ei7uRE56Dryho45WNreUgsjRlcPWs5UCDjHXJ347gIsaoUdxIGPh8EHCQDPja5sLuWbcNZgk2gVK5+bQppv6Jp5t+keldlB4cuunIOXTge9sjvg2EtOgkrDYW7/fxhUjK8uYHVfdcZrrCjnloTjSUsi1WwfF7tdM7TFoY9E2WyfUSwOvAtlYBpDCiI2ZFgS3uyuzCwpsnzGbKAXN9vZiXHyo0nMDESy9KS360dSZ3NucKXhKv8WL+FrtpQXXi6qKs5uUwpVM327Gdi55zt2AZ5j+4oOrEih9PvnxIa523qIBjovc4UhN8Du3LX0AafCjkdy8Mmd4My0ne6hNOXgJZDHl4oZ78FiVFlLM5b+uVym0n9z6gPQNstMzEJ/72UYlIquQF7l2VYQ7H3vtcGA+WoVBkqNBrbrOJP+rrnyNaSotl7YqQ29vbjH5Z97WJ5pX166Xcer5nnk5KFSUnIDsyx6XHF7Ji6ogpxuCh6XoWR/6wMrshvOaFvVP9tHFOh10Lmn9sVVhsAOYGtEWkcImItRB7L4Rbmxg9i1VUKAyEYZ+tgn8MRW/Pc6PKTTYJ7YCJ4n2NfSHos1Ipi8Z3ZIqGwIlGSf7P8rlsdguKqXa/IuahOZlGnYUhVW7Tycd2v9VJYwi/WlpWk69/xDl5MB161rHovWP6+vlnTJ3gD3kCy+3s6+M+st1X0LcrlxMEuGt7SZeJKRPvNo+zxBqaoXpul4EMBcPWp8HMRx/nWcl93jUNd8W9PgzN8OHdV49lRbHRwC7LG99zKcEXjv6CJvd0QDqPZShG1uuYzEGGfUkUEWOcuW0EkLsF62p7T25SkfNhPrx6oIXjqoNPLxXR7D5VmrC0HsaTqljLZnYh8SaUOVTGr/Iv8+qX+3HN2M14qUE7u4mCuqA9UiToUiuvUrnCJrnXvF/PSkK9Od38RkGlXtnDOSD9SVfHVoBHraeEF6JOvFIpOftWRREM95dXFHRazjAScElxT5cwW8k5IXuQDhZmk5RBDI1ifIOR1RwtNVScJ/IkfhTGOVgV3jd3WAAMMZhVA4YxwMDJDx0arb6Jpbhr0bRkhEo9Ka3YvqaezE+khi277HkHWFE2pjzo/JY96F2jEvkM+Q1iQKDpdIu+e4n1mYNIVRPtPRJLqJnSZdabTk4EvukwxhLBBbA5eavGIo6QtVyvI9hSYMQkMFdkM35npO6nx3K07ZlrehALS8qW9uqFBun/STy840JTNDU9TBTSvj8Atekdr409sSFqaarXTyjEo1+XqnOF0xF+YT3zv5zJX0brQVzXo44hJzAVlV7HA0go6Urm77QM3LkrmfDkKhJPzG1humVxZPyCGoZY0u0vVLHaGyuxDE2Y7clwlZFRd3pc7vCWHLNGqxdEEmJsfxfRkHtlCEp3j3D5olKl9o+UtdA5X4T3HBONR6d5abMAEyu2g5KZL7guppvHy5xm2Br6sA4Ps7r2EOuDp18aOGUYPjoy9zG2SioHQ4iwny/+aRmxoBFx1SdM3xdg4xMtyskd7bnjMDIc+0vjllxHAEAOPtFp0AqfrBIbBaLNtgXgUXLX764BTsizOgar4UTWJpfJf5DCZC7L5uM1bSeNoveRk10l84q0TYvuOuQjKpu3BJZDbastGtkR0uVNrk1zAVlOauRyG9NulFRXEfQ5QqoKkcGf4upMmZTW29zn+itRKdaCK45g0M72Ej6cNeB6Sju8lSINmr/PaYqYVB/ESMnQ65IMEb1g/RgD", + "page_age": null, "title": "Package ''ggplot2''", "type": "web_search_result", + "url": "https://cran.r-project.org/web/packages/ggplot2/ggplot2.pdf"}, {"encrypted_content": + "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", + "page_age": null, "title": "NEWS", "type": "web_search_result", "url": "https://cran.r-project.org/web/packages/ggplot2/news/news.html"}, + {"encrypted_content": "EocKCioICxgCIiQ1MzY3Y2M0OC03OTYwLTQ5NmUtOTkyYS1kYmExZTRkMDViNDISDOkIDZBmEkdkY/ku9hoMgAwxHoCa/5fnY+IPIjD6RCpbsfnCMZsBD7eRZY94juwK0umyC97J959tC9DVYSTkf/a0ISyP/xcfuZzFIX8qigli00/DURjFhLLgUyA1w1cJ5/EVP/UFkZU12WCAYRKV0frD7VPLrzN4gWBYGwGsGOcS984aU16D5JSOgIOOXt3SPABtw2h7fw1FujDCg6pnr8juekw5I4SikzCeLEpigWg+vmc4zfZffsJuoBQaD6jxObaMJhTybDTjWKmMdTz3Eq97FLllTgCXAsErNGokfTY/yxJAo9DxZcZYuMl489OG5ThmbZLe1aQeAZVr3YFfS+XMa+0L885oCoel+S0WIAEOW3xXuzIw9tq+oMKxZvAdYA7usK1WihBWPl/ayTIOuvzL7XFX6SnuSNT7QDgfelRAfl434aSVdr+Y27WitoRNmODJov3zLGjP06pE5cPdeB9Bsvzb6YsHPvSx3FxfBH2+fx2kuCd10HeDo39cpVfYK5zBrbqPUKbECGuv0LajYVT1G7h4PBDyjWEMQJ3SHZCsxJSI+D2V9vDxPDZ5/oLy+zq7TXIkBskDW13JD2pfdRdztXboffddHqE3jIQH/byodnyV/+FPSwVrTaYxwBO7A2dMC/vFpKe1rD5AWdoCbzgqVNgJFjLLEiffSXIIfItrKNf7IwnjMLCVaBaZ7PVJ7Mk5ZiymrhooXB+DHUZabgbjgRFSe0TKju26ZeH+5qw7NLWfIFaWW6ZdfZthayNnIvPhVbdo9gHlb0vtHtLIzo/tV4k2/DV0Efvo8nGLoZ3bRRH3/oeHqGtQB99bTfHLq+1HN2UVsLXlQGDMF0W5b079aoUoCmSM5A8RSdLaovgpzTYjgeutLP7M9KOn9LR0+BTNAj1iDGpRUnKqMqQ1j78aKQmqNs7X64nVT5jOzSaZSwgWyRxTrLz/kcKX2ZUOOH1LjHgfwfbh8OMbGLCkBPOkGoUjhs96qtUN+M9eVK4s9GMDGHNvSFEtlDIfIzo9F9YxM6rPL7cBMIeDBKM1XUsOaueZdgznduuVi89l2EmfPCO8nfxMOgjILjwakdMG6Pvdwm+I2jyH1jOkUrD0z0ihHVSsVVGXWoUvO1yTldIrgVZoSGlZnF8HcmJZ8hqGYhFt78hCOrokBhWU64140ERmowwM1acKif9CBsocpRGHmNdaF8TtOp5Of74fkb3MqLhpLzmK6eCItOl2R1DiDniTMPDvpQXGF7t6RLVFAhj1WM0ZaS2v5sqF3gp1Vjc66rx9lTxPKfsEpTc+XBZ7QtWZ+14G8/TgUOzMVuc7R/y9iZcSchbalagerhaGypAhA8ZJ77UYEi5dMzE5ij8cN8KBIxEDEmG8UUrU+85C2nsXstpVGS27R88vgcR/nhD/ngU6Y0CFd28GogEANt+wpnP5tgf37SJpDDmZCKGOwkHYE16mxsLXWLSOsnuLZTFK4BqN4U9Sjg8Nt+qlFPFnJsn99MpNlGPMObThGAJ5GIu23CsqDcofpmU1SPJivJSQY+NPCh6XmLZElCvBg9DIi7IHCW3c2A0r54n/vdJ/73MoODyk6pfDT6SOsgPVUiFv8FBH8o79eFZE21pfuhiQSxkMr4T/QIs/3LIpuOjYddTSqLs2FaQQJIxVGAM=", + "page_age": "October 17, 2025", "title": "ggpubr: ''ggplot2'' Based Publication + Ready Plots - CRAN", "type": "web_search_result", "url": "https://cran.r-project.org/package=ggpubr"}], + "tool_use_id": "srvtoolu_019vghbahbRKPzBwadunDFSW", "type": "web_search_tool_result"}, + {"text": "ggplot2 1.0.0 was released on 2014-05-21", "type": "text"}, {"text": + ".", "type": "text"}]}, {"role": "user", "content": [{"text": "What month was + that?", "type": "text", "cache_control": {"type": "ephemeral", "ttl": "5m"}}]}], + "model": "claude-haiku-4-5-20251001", "stream": true, "system": [{"type": "text", + "text": "[empty string]", "cache_control": {"type": "ephemeral", "ttl": "5m"}}], + "tools": [{"name": "web_search", "type": "web_search_20250305"}]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '43677' + Content-Type: + - application/json + Host: + - api.anthropic.com + X-Stainless-Async: + - 'false' + anthropic-version: + - '2023-06-01' + x-stainless-read-timeout: + - '600' + x-stainless-timeout: + - NOT_GIVEN + method: POST + uri: https://api.anthropic.com/v1/messages + response: + body: + string: 'event: message_start + + data: {"type":"message_start","message":{"model":"claude-haiku-4-5-20251001","id":"msg_01TMSeCrqGLutSHQmj8Ls89R","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":37,"cache_read_input_tokens":17269,"cache_creation":{"ephemeral_5m_input_tokens":37,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} } + + + event: content_block_start + + data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} } + + + event: content_block_delta + + data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"That"} } + + + event: content_block_delta + + data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" + was May 2"} } + + + event: ping + + data: {"type": "ping"} + + + event: content_block_delta + + data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"014."} } + + + event: content_block_stop + + data: {"type":"content_block_stop","index":0 } + + + event: message_delta + + data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":3,"cache_creation_input_tokens":37,"cache_read_input_tokens":17269,"output_tokens":10} } + + + event: message_stop + + data: {"type":"message_stop" } + + + ' + headers: + CF-RAY: + - 9b7d970fccf94828-DEN + Cache-Control: + - no-cache + Connection: + - keep-alive + Content-Type: + - text/event-stream; charset=utf-8 + Date: + - Fri, 02 Jan 2026 22:11:04 GMT + Server: + - cloudflare + Transfer-Encoding: + - chunked + X-Robots-Tag: + - none + anthropic-ratelimit-input-tokens-limit: + - '4000000' + anthropic-ratelimit-input-tokens-remaining: + - '3999000' + anthropic-ratelimit-input-tokens-reset: + - '2026-01-02T22:11:04Z' + anthropic-ratelimit-output-tokens-limit: + - '800000' + anthropic-ratelimit-output-tokens-remaining: + - '800000' + anthropic-ratelimit-output-tokens-reset: + - '2026-01-02T22:11:04Z' + anthropic-ratelimit-requests-limit: + - '4000' + anthropic-ratelimit-requests-remaining: + - '3999' + anthropic-ratelimit-requests-reset: + - '2026-01-02T22:11:04Z' + anthropic-ratelimit-tokens-limit: + - '4800000' + anthropic-ratelimit-tokens-remaining: + - '4799000' + anthropic-ratelimit-tokens-reset: + - '2026-01-02T22:11:04Z' + cf-cache-status: + - DYNAMIC + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + x-envoy-upstream-service-time: + - '429' + status: + code: 200 + message: OK +version: 1 diff --git a/tests/_vcr/test_provider_anthropic/test_anthropic_web_search_citations.yaml b/tests/_vcr/test_provider_anthropic/test_anthropic_web_search_citations.yaml new file mode 100644 index 00000000..9d4b5567 --- /dev/null +++ b/tests/_vcr/test_provider_anthropic/test_anthropic_web_search_citations.yaml @@ -0,0 +1,125 @@ +interactions: +- request: + body: '{"max_tokens": 4096, "messages": [{"role": "user", "content": [{"text": + "When was ggplot2 1.0.0 released to CRAN? Answer in YYYY-MM-DD format.", "type": + "text", "cache_control": {"type": "ephemeral", "ttl": "5m"}}]}], "model": "claude-haiku-4-5-20251001", + "stream": true, "system": [{"type": "text", "text": "[empty string]", "cache_control": + {"type": "ephemeral", "ttl": "5m"}}], "tools": [{"name": "web_search", "type": + "web_search_20250305"}]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '413' + Content-Type: + - application/json + Host: + - api.anthropic.com + X-Stainless-Async: + - 'false' + anthropic-version: + - '2023-06-01' + x-stainless-read-timeout: + - '600' + x-stainless-timeout: + - NOT_GIVEN + method: POST + uri: https://api.anthropic.com/v1/messages + response: + body: + string: "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-haiku-4-5-20251001\",\"id\":\"msg_01XV4iJ3eseqSSb3QWJqJPeu\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"usage\":{\"input_tokens\":2247,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"cache_creation\":{\"ephemeral_5m_input_tokens\":0,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":26,\"service_tier\":\"standard\"}} + \ }\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"server_tool_use\",\"id\":\"srvtoolu_01QaGk4V8LXm1Sxk2wPAdW8n\",\"name\":\"web_search\",\"input\":{}} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"query\\\": + \\\"g\"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"gplot2 + 1.0.0\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\" + CRAN releas\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"e + \"}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"date\\\"}\"} + \ }\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0 + \ }\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"web_search_tool_result\",\"tool_use_id\":\"srvtoolu_01QaGk4V8LXm1Sxk2wPAdW8n\",\"content\":[{\"type\":\"web_search_result\",\"title\":\"CRAN: + Package ggplot2\",\"url\":\"https://cran.r-project.org/package=ggplot2\",\"encrypted_content\":\"Eo4DCioICxgCIiQ1MzY3Y2M0OC03OTYwLTQ5NmUtOTkyYS1kYmExZTRkMDViNDISDMdDpFnrjN5MbgnxeBoMzj4B74oD6PRxm9MUIjCvB7g3tIcXkPuWKsjS2z0RiYh5Ut0tTsOCZvY2sEAZ0G7HgBmvimqqJHn3GO9H0lYqkQKdppmGS4L8XthS5KYrpbj882yDVL+MFNaR78f9cYyICwxGVSEfSRPXVpvZLMf68BVEN6ZuozjQ8vmLtCSHzFziPCjmdOFRimiqOsdt/h3uu1vQLvk/XjXuZZkAEWMCeRX5apDhl5VmeBuaFP1IWIaroEloCC4zEi+azz9VycBs1PTO/ujBTp7cfbK0x3j8fFyRDAybflLhCJpWwpqGTYUrk0DriwG2leEm/D3qdYhONZOFE6lm1nkXcxZjGb68DYrng3tEPzAwRIyOLGpYqGhHydlr6JsB3FuNEhEclmVQ1NmmUWBeiSM0rZSIY6hSfRGOwhozjD5ytPtIH4Az2g6i6BWNRzWS9kuASfipHHEkij0YAw==\",\"page_age\":\"November + 14, 2025\"},{\"type\":\"web_search_result\",\"title\":\"Changelog \u2022 ggplot2\",\"url\":\"https://ggplot2.tidyverse.org/news/index.html\",\"encrypted_content\":\"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\",\"page_age\":null},{\"type\":\"web_search_result\",\"title\":\"ggplot2 + - Wikipedia\",\"url\":\"https://en.wikipedia.org/wiki/Ggplot2\",\"encrypted_content\":\"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\",\"page_age\":\"4 + days ago\"},{\"type\":\"web_search_result\",\"title\":\"Releases \xB7 tidyverse/ggplot2\",\"url\":\"https://github.com/tidyverse/ggplot2/releases\",\"encrypted_content\":\"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\",\"page_age\":null},{\"type\":\"web_search_result\",\"title\":\"Releases + \xB7 cran/ggplot2\",\"url\":\"https://github.com/cran/ggplot2/releases\",\"encrypted_content\":\"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\",\"page_age\":null},{\"type\":\"web_search_result\",\"title\":\"ggplot2 + R Package Stats, Author, Search and Tutorials | Examples | Downloads | Statistics + | Citations\",\"url\":\"https://rpkg.net/package/ggplot2\",\"encrypted_content\":\"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\",\"page_age\":null},{\"type\":\"web_search_result\",\"title\":\"New + version of ggplot2, new problems \xB7 Issue #255 \xB7 pbiecek/archivist\",\"url\":\"https://github.com/pbiecek/archivist/issues/255\",\"encrypted_content\":\"Ev4KCioICxgCIiQ1MzY3Y2M0OC03OTYwLTQ5NmUtOTkyYS1kYmExZTRkMDViNDISDMQzCTDfaczyydN5qhoMAF/lbo6b2cju8v+KIjBRSvsCf0rhBvyDDAOTMbILZa7G3GVNcjGrr4DR//3UcfuzkXehbphHc4bJ0D0M13gqgQpMG32MWP1Gbrag1XdqP0sAra3QqATBhy36zUx9E4Eh7i8APnqgbAa8JEbjRZQIw2dDB3MCiYxagd0U4LTfHKAFfwDWukfbE2b/WArVlxGX9d2+887sCRSjZYy00mun1Uem1QIKch57EoE4z86yHdsz8YOmteWI4PRfYOIlgDid2Bo3cvT6ytkzfSWyqVyDpYMrIPuq75PyEHxnSav7C0/JSRZvUwqiw8Fyqgdg8FaEHklNF1EZKWVj57arjtpMUvglpFT12OSjNYlarQLkPH+dynVojlVjLckAp8hT0liBYc+klk3YeTV7wFeFOoJR5DKxw4SyU6jkFI0sbgPWMVIBnSQ/T1IWaD4C+wtFiWh7suZZvcaD5Sw/x7I4i5o39yoEoYp21mM3hF2zcwH9kGPhvK3Ue7tUN3SmI5AHc2TynG+bykwNBldjU3vUHHS8iQ442X8U+S2L32/S61IwwcPT1KrKIYvZNoN5s5B7VxR+JDTWJuvhnr7uFlhV0QlRDOy9P9uhOtCJg0FlC86mNkI0SNTbe1gsEdrTsuZHCc3QXcyk1AiGGArnl5KZLVPE2cJ3VUeNF2vAG6pT850r5uaifLy+xRdM9LfMEIl0EPa+zbwu8yeogFsfKZSCge/A1/TwDUGJmx5rZb3gITwZbHglM1ZN2tHCeuS0RZNZGc0bF20cuv5DTmbSh2QWR9DfrTnsVoRZ7zN1oHy4uPS0S1Pbyg9AUfyWcbGUDYDD3iYxM+VVnBY+dQkoejAP5kkobw/DhII7yI8iuQaPgEEivB7yWSL+s2qQg3cT1ttb0bO4JBHbm2q2f3yJPJVzv3jqi08j4JCWuSzhaYlXM/wQ9KeMGtqxJ1VvTdIqZEhEloElOz11+IuvUNhPUytzCfZ3qesSXnLhbz0+mMhuPmluRomQTiCHXPZnAP/5AO5FyGQO7KstxFzgsBrcxOvZS7KT869xZesIi8F7z7Tt0C2jZ+QA9+ssiZMBFsN9k3Q21B2+wmeoYu6lG3fqftY9+q4k10OCb6K/Lp9d6Azk6c23uWmSYWZSlbL0BgLqeG92k8LvAulbRbQH7OIhQ+5O34gWJqy+dmoicBVLfxPUZSRC0TcvZ/9WuBYMnp5WRYtriRcev/lIcxAgGoEVDZl9tSwIWabS/4+7Mx/fecshMAQS3KPCIuEr01QvoW/LzRBjzeGy1FeSwZC8n3pzobh5XOt1alponr5qfs7SO9CFpFd3D5D44b3jhvlH6FD0DNv9snUXO4YAh8kMFXU6JUI70HhcjgvAWxBm11wc6ysvJ514HyjwPhKZLhoocH0fccn7VAuWe73HlKxPCtk+3amDtPR3CH6OUFE71MhNfV82Th1/GNBkxcNVbbuV3KOSavkPgzTkfokBvOS0YhoPKW1pW1Ukri/hbvAjd1Kvj0Pb3vsMYm3DGqHVJPut1PtUuuOy+PIMYxQPppvnxZC2cTLij0i1u+kyG9fAKyvIYordMFnfMuUCs0WSYDYN9oS+y0kBxqPKWelNMDerAiTtBk2BBtlhDNbqJWSp1dO6Us8ymDTdSMt/4SmKkuGn+l4qBITNTz4x8u0eOR6xfa9TFwsPxgywBzlJZmje6v2QUK63xaetkeWBYpX20g7MkuKNGX70kzJFy8nEmVUoeo4q7E3aQ9CU5QbFOh1S+BtJeOQ0LI1K6NpAk3scWq/Tt6jpwzn/a8BGYR8YAw==\",\"page_age\":null},{\"type\":\"web_search_result\",\"title\":\"Package + 'ggplot2'\",\"url\":\"https://cran.r-project.org/web/packages/ggplot2/ggplot2.pdf\",\"encrypted_content\":\"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\",\"page_age\":null},{\"type\":\"web_search_result\",\"title\":\"NEWS\",\"url\":\"https://cran.r-project.org/web/packages/ggplot2/news/news.html\",\"encrypted_content\":\"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\",\"page_age\":null},{\"type\":\"web_search_result\",\"title\":\"ggpubr: + 'ggplot2' Based Publication Ready Plots - CRAN\",\"url\":\"https://cran.r-project.org/package=ggpubr\",\"encrypted_content\":\"EocKCioICxgCIiQ1MzY3Y2M0OC03OTYwLTQ5NmUtOTkyYS1kYmExZTRkMDViNDISDHZnLzY3L0oHo3ZBvRoMJyCod8ZByx4aCvT3IjB+h+0XR1zUXcZPCJ36AVBAm/n9qAks6wruI58dXne3lU7ioRNnGb2xDSXXV9jSpE4qigm3fxKe8hf44gEXK4aBQ3hgE6XuP2mYCtbkLT1YcV4F3T9+BFuhwk/tD1Nk4GQi3Hgsyw5/vuMBn9S6mOpcOj2lSDsolmjsDYRSxLqefcmEaa+6FikOs/hR2h3j+Sk8luE1P4m0Qiv+2zFpFWuKvKaiLJNVIWmZ+UnUIMt+jxDZN6NA2fAvj9aCBSv7Jdq+l+HIA5aCM/KXiEaMYH+EtSi+0TqOs4zlubfZQXnEipwAgeqylDVw8Zsd8HTmhjM7pQTyhB9iy0/t4VX7+A08v2Fk5PZ8xkICHi92vfHe1K7NXr/NuFRcvP8bPzBJN/3NyCNM7UxOPP3ZvCoqTWkIRLIL1zDUtADZHPmHueK5y0pseeycuOx77RhxtRSktAUAQknJoklnOqfQFNL32PM+wb89VSkJLbrSF+L0ggiZz8xq32v+I1e7ylpRMSETL/B+hhZJmH3pJlwzH2jcFYmDitKr3gRQchwpamJ96KF/flLjmFj/chQLYl01PsHaWA7IJkMOSyiw8hBtyyXcVJOAm+4kKYRdUGu787evZp+Tx+aB+yTu8zTtIpI7VOpK9jETuOorTEvm+CHPhaA+jkDAsLR+mU/9Ob6zCL953y+hCpI9XsYlbg5fiWOIgv13dl2cMDlosMrmncEuF/zripetocO1Usqlxm/EjVsDEL+dYWDV/6ILXjfaktinYWsl2Y2OVkXAnmR3vaNktEnMlj8klNZQivLrdp+7+09Gc+8xYyTky6eyfNJwkvFBF6Fr1lzVEZV/mCsuOv5P8nU/97E21D5k3WfhDzPKVsfiiUNOP+jg+xBTKQSam+iaCIKmfEyOtNp6W8XEglLY+PYE0CCRgSbRcNNaGqRAnVLyWu3cs/RCyE34C3r73uz4q/ercbuh1MgVYGLOlbeMmY5sy14XJbaskCaupfGDSxVdGxe4a3ahfvWp9fa4p827CTE8srLHObH2dqf/abw6PqhPWU29l0xKpjLxiL72p/zgjA/p1mfEnoQAo6ZGmGlPv0T8abvIwy+DlEWIVMwCqP3Mkt3QzwaBLsbyjI+ZrdpbeUiLGbyG2fE1snJgIaBLdzPGxipwjflzUwbWyVfiYL0C38WBX6Wl094CvePm+A+qZLJCX4flP7cjX4Mvh7stvfkLUdRZlKCi3UcUWwIQvE8h/C6/B6tMJN+yqA5pMvvIJbgyxx3M/wsIWIJxiBRu4X3z1N4as0c05KyTsLIHZecwcSpUMbBTxSByMu85dwib/eck9mAt/GcPy3nlO6THK7DrVIuLE2ps3gQF4DAzvOdjwyOkMvVWOgqo7eH14Y+2Dc1T98TvSm0hTL/KC6Za5D8jg+c5O/lO3YOMKBMKyQTtMINVOacPLw1NsY2JYgrjXRd0ZC9zU9mkj4PgCih6XgWB0QBO2SHpFbEKutNa8l/JCV8VN+xME+cxIqopH3KIadB9EQgdZPl0ztCfKVPFZZ3ZdsXsZE2yVPOEtabOzBf68ZO/LL/xSPfeFRCSPWxdMPlSRM3IFgYT1i6M3Au+IzUzFSdaP6+khX/q2tlY9l3WGAM=\",\"page_age\":\"October + 17, 2025\"}]} }\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1 + \ }\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":2,\"content_block\":{\"citations\":[],\"type\":\"text\",\"text\":\"\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"citations_delta\",\"citation\":{\"type\":\"web_search_result_location\",\"cited_text\":\"... + 0.5.1 (2007-06-10 21:49), 0.5.2 ... (2012-09-04 08:16), 0.9.3.1 (2013-03-02 + 15:57), 0.9.3 (2012-12-05 13:11), 1.0.0 (2014-05-21 15:36), 1.0.1 (201...\",\"url\":\"https://rpkg.net/package/ggplot2\",\"title\":\"ggplot2 + R Package Stats, Author, Search and Tutorials | Examples | Downloads | Statistics + | Citations\",\"encrypted_index\":\"Eo8BCioICxgCIiQ1MzY3Y2M0OC03OTYwLTQ5NmUtOTkyYS1kYmExZTRkMDViNDISDIpC07dmq4VIhJqJqxoMuZIOISYbZwrKi+dDIjBXRtCCFauZlFKpzxYW0ozathAwKVmwvvwKvCkJFA27SX5KtIV5c7CRaN3pIrwONy0qEw5meNDahdlC+T7ZZDEiur0Ix0gYBA==\"}} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"text_delta\",\"text\":\"ggplot\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"text_delta\",\"text\":\"2 + version\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"text_delta\",\"text\":\" + 1\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"text_delta\",\"text\":\".0\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"text_delta\",\"text\":\".0 + was released on 2\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"text_delta\",\"text\":\"014\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"text_delta\",\"text\":\"-05\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"text_delta\",\"text\":\"-21\"} + \ }\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":2 + \ }\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":3,\"content_block\":{\"type\":\"text\",\"text\":\"\"} + \ }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":3,\"delta\":{\"type\":\"text_delta\",\"text\":\".\"} + \ }\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":3 + \ }\n\nevent: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\",\"stop_sequence\":null},\"usage\":{\"input_tokens\":2254,\"cache_creation_input_tokens\":17269,\"cache_read_input_tokens\":0,\"output_tokens\":112,\"server_tool_use\":{\"web_search_requests\":1}} + \ }\n\nevent: message_stop\ndata: {\"type\":\"message_stop\" }\n\n" + headers: + CF-RAY: + - 9b7e26f4ebd251f1-DEN + Cache-Control: + - no-cache + Connection: + - keep-alive + Content-Type: + - text/event-stream; charset=utf-8 + Date: + - Fri, 02 Jan 2026 23:49:18 GMT + Server: + - cloudflare + Transfer-Encoding: + - chunked + X-Robots-Tag: + - none + anthropic-ratelimit-input-tokens-limit: + - '4000000' + anthropic-ratelimit-input-tokens-remaining: + - '3999000' + anthropic-ratelimit-input-tokens-reset: + - '2026-01-02T23:49:18Z' + anthropic-ratelimit-output-tokens-limit: + - '800000' + anthropic-ratelimit-output-tokens-remaining: + - '800000' + anthropic-ratelimit-output-tokens-reset: + - '2026-01-02T23:49:18Z' + anthropic-ratelimit-requests-limit: + - '4000' + anthropic-ratelimit-requests-remaining: + - '3999' + anthropic-ratelimit-requests-reset: + - '2026-01-02T23:49:18Z' + anthropic-ratelimit-tokens-limit: + - '4800000' + anthropic-ratelimit-tokens-remaining: + - '4799000' + anthropic-ratelimit-tokens-reset: + - '2026-01-02T23:49:18Z' + cf-cache-status: + - DYNAMIC + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + x-envoy-upstream-service-time: + - '520' + status: + code: 200 + message: OK +version: 1 diff --git a/tests/_vcr/test_provider_google/test_google_web_fetch.yaml b/tests/_vcr/test_provider_google/test_google_web_fetch.yaml new file mode 100644 index 00000000..15e09750 --- /dev/null +++ b/tests/_vcr/test_provider_google/test_google_web_fetch.yaml @@ -0,0 +1,148 @@ +interactions: +- request: + body: '{"contents": [{"parts": [{"text": "What''s the first movie listed on https://rvest.tidyverse.org/articles/starwars.html?"}], + "role": "user"}], "tools": [{"urlContext": {}}], "generationConfig": {"temperature": + 0}}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '212' + Content-Type: + - application/json + Host: + - generativelanguage.googleapis.com + x-goog-api-client: + - google-genai-sdk/1.56.0 gl-python/3.12.11 + method: POST + uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse + response: + body: + string: "data: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"The + first movie listed\"}],\"role\": \"model\"},\"index\": 0,\"groundingMetadata\": + {},\"urlContextMetadata\": {\"urlMetadata\": [{\"retrievedUrl\": \"https://rvest.tidyverse.org/articles/starwars.html\",\"urlRetrievalStatus\": + \"URL_RETRIEVAL_STATUS_SUCCESS\"}]}}],\"usageMetadata\": {\"promptTokenCount\": + 25,\"candidatesTokenCount\": 26,\"totalTokenCount\": 1219,\"promptTokensDetails\": + [{\"modality\": \"TEXT\",\"tokenCount\": 25}],\"toolUsePromptTokenCount\": + 1130,\"toolUsePromptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": + 1130}],\"thoughtsTokenCount\": 38},\"modelVersion\": \"gemini-2.5-flash\",\"responseId\": + \"VDVYaY2XOYqM_uMPi8-j8AY\"}\r\n\r\ndata: {\"candidates\": [{\"content\": + {\"parts\": [{\"text\": \" on https://rvest.tidyverse.org/articles/starwars.html + is \\\"\"}],\"role\": \"model\"},\"index\": 0,\"groundingMetadata\": {}}],\"usageMetadata\": + {\"promptTokenCount\": 25,\"candidatesTokenCount\": 44,\"totalTokenCount\": + 1237,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 25}],\"toolUsePromptTokenCount\": + 1130,\"toolUsePromptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": + 1130}],\"thoughtsTokenCount\": 38},\"modelVersion\": \"gemini-2.5-flash\",\"responseId\": + \"VDVYaY2XOYqM_uMPi8-j8AY\"}\r\n\r\ndata: {\"candidates\": [{\"content\": + {\"parts\": [{\"text\": \"The Phantom Menace\\\".\"}],\"role\": \"model\"},\"finishReason\": + \"STOP\",\"index\": 0,\"groundingMetadata\": {\"groundingChunks\": [{\"web\": + {\"uri\": \"https://rvest.tidyverse.org/articles/starwars.html\",\"title\": + \"Star Wars films (static HTML) \u2022 rvest\"}}],\"groundingSupports\": [{\"segment\": + {\"endIndex\": 100,\"text\": \"The first movie listed on https://rvest.tidyverse.org/articles/starwars.html + is \\\"The Phantom Menace\\\"\"},\"groundingChunkIndices\": [0]}]}}],\"usageMetadata\": + {\"promptTokenCount\": 25,\"candidatesTokenCount\": 49,\"totalTokenCount\": + 1242,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 25}],\"toolUsePromptTokenCount\": + 1130,\"toolUsePromptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": + 1130}],\"thoughtsTokenCount\": 38},\"modelVersion\": \"gemini-2.5-flash\",\"responseId\": + \"VDVYaY2XOYqM_uMPi8-j8AY\"}\r\n\r\n" + headers: + Alt-Svc: + - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 + Content-Disposition: + - attachment + Content-Type: + - text/event-stream + Date: + - Fri, 02 Jan 2026 21:15:00 GMT + Server: + - scaffolding on HTTPServer2 + Server-Timing: + - gfet4t7; dur=1102 + Transfer-Encoding: + - chunked + Vary: + - Origin + - X-Origin + - Referer + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-XSS-Protection: + - '0' + status: + code: 200 + message: OK +- request: + body: '{"contents": [{"parts": [{"text": "What''s the first movie listed on https://rvest.tidyverse.org/articles/starwars.html?"}], + "role": "user"}, {"parts": [{"text": "The first movie listed"}, {"text": " on + https://rvest.tidyverse.org/articles/starwars.html is \""}, {"text": "The Phantom + Menace\"."}], "role": "model"}, {"parts": [{"text": "Who directed it?"}], "role": + "user"}], "tools": [{"urlContext": {}}], "generationConfig": {"temperature": + 0}}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '446' + Content-Type: + - application/json + Host: + - generativelanguage.googleapis.com + x-goog-api-client: + - google-genai-sdk/1.56.0 gl-python/3.12.11 + method: POST + uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse + response: + body: + string: "data: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"George + Lucas directed \\\"The Phantom Menace\\\".\"}],\"role\": \"model\"},\"finishReason\": + \"STOP\",\"index\": 0,\"groundingMetadata\": {\"groundingChunks\": [{\"web\": + {\"uri\": \"https://rvest.tidyverse.org/articles/starwars.html\",\"title\": + \"Star Wars films (static HTML) \u2022 rvest\"}}],\"groundingSupports\": [{\"segment\": + {\"startIndex\": 1,\"endIndex\": 43,\"text\": \"George Lucas directed \\\"The + Phantom Menace\\\"\"},\"groundingChunkIndices\": [0]}]},\"urlContextMetadata\": + {\"urlMetadata\": [{\"retrievedUrl\": \"https://rvest.tidyverse.org/articles/starwars.html\",\"urlRetrievalStatus\": + \"URL_RETRIEVAL_STATUS_SUCCESS\"}]}}],\"usageMetadata\": {\"promptTokenCount\": + 58,\"candidatesTokenCount\": 31,\"totalTokenCount\": 1282,\"promptTokensDetails\": + [{\"modality\": \"TEXT\",\"tokenCount\": 58}],\"toolUsePromptTokenCount\": + 1159,\"toolUsePromptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": + 1159}],\"thoughtsTokenCount\": 34},\"modelVersion\": \"gemini-2.5-flash\",\"responseId\": + \"VjVYaYPpEbTQ_uMP_vPbaQ\"}\r\n\r\n" + headers: + Alt-Svc: + - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 + Content-Disposition: + - attachment + Content-Type: + - text/event-stream + Date: + - Fri, 02 Jan 2026 21:15:02 GMT + Server: + - scaffolding on HTTPServer2 + Server-Timing: + - gfet4t7; dur=1074 + Transfer-Encoding: + - chunked + Vary: + - Origin + - X-Origin + - Referer + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-XSS-Protection: + - '0' + status: + code: 200 + message: OK +version: 1 diff --git a/tests/_vcr/test_provider_google/test_google_web_search.yaml b/tests/_vcr/test_provider_google/test_google_web_search.yaml new file mode 100644 index 00000000..df73a44b --- /dev/null +++ b/tests/_vcr/test_provider_google/test_google_web_search.yaml @@ -0,0 +1,189 @@ +interactions: +- request: + body: '{"contents": [{"parts": [{"text": "When was ggplot2 1.0.0 released to CRAN? + Answer in YYYY-MM-DD format."}], "role": "user"}], "tools": [{"googleSearch": + {}}], "generationConfig": {"temperature": 0}}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '199' + Content-Type: + - application/json + Host: + - generativelanguage.googleapis.com + x-goog-api-client: + - google-genai-sdk/1.56.0 gl-python/3.12.11 + method: POST + uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse + response: + body: + string: "data: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"ggplot2 + version 1.0.0 was released to CRAN on 2014-05-21.\"}],\"role\": \"model\"},\"finishReason\": + \"STOP\",\"index\": 0,\"groundingMetadata\": {\"searchEntryPoint\": {\"renderedContent\": + \"\\u003cstyle\\u003e\\n.container {\\n align-items: center;\\n border-radius: + 8px;\\n display: flex;\\n font-family: Google Sans, Roboto, sans-serif;\\n + \ font-size: 14px;\\n line-height: 20px;\\n padding: 8px 12px;\\n}\\n.chip + {\\n display: inline-block;\\n border: solid 1px;\\n border-radius: 16px;\\n + \ min-width: 14px;\\n padding: 5px 16px;\\n text-align: center;\\n user-select: + none;\\n margin: 0 8px;\\n -webkit-tap-highlight-color: transparent;\\n}\\n.carousel + {\\n overflow: auto;\\n scrollbar-width: none;\\n white-space: nowrap;\\n + \ margin-right: -12px;\\n}\\n.headline {\\n display: flex;\\n margin-right: + 4px;\\n}\\n.gradient-container {\\n position: relative;\\n}\\n.gradient {\\n + \ position: absolute;\\n transform: translate(3px, -9px);\\n height: 36px;\\n + \ width: 9px;\\n}\\n@media (prefers-color-scheme: light) {\\n .container + {\\n background-color: #fafafa;\\n box-shadow: 0 0 0 1px #0000000f;\\n + \ }\\n .headline-label {\\n color: #1f1f1f;\\n }\\n .chip {\\n background-color: + #ffffff;\\n border-color: #d2d2d2;\\n color: #5e5e5e;\\n text-decoration: + none;\\n }\\n .chip:hover {\\n background-color: #f2f2f2;\\n }\\n .chip:focus + {\\n background-color: #f2f2f2;\\n }\\n .chip:active {\\n background-color: + #d8d8d8;\\n border-color: #b6b6b6;\\n }\\n .logo-dark {\\n display: + none;\\n }\\n .gradient {\\n background: linear-gradient(90deg, #fafafa + 15%, #fafafa00 100%);\\n }\\n}\\n@media (prefers-color-scheme: dark) {\\n + \ .container {\\n background-color: #1f1f1f;\\n box-shadow: 0 0 0 1px + #ffffff26;\\n }\\n .headline-label {\\n color: #fff;\\n }\\n .chip + {\\n background-color: #2c2c2c;\\n border-color: #3c4043;\\n color: + #fff;\\n text-decoration: none;\\n }\\n .chip:hover {\\n background-color: + #353536;\\n }\\n .chip:focus {\\n background-color: #353536;\\n }\\n + \ .chip:active {\\n background-color: #464849;\\n border-color: #53575b;\\n + \ }\\n .logo-light {\\n display: none;\\n }\\n .gradient {\\n background: + linear-gradient(90deg, #1f1f1f 15%, #1f1f1f00 100%);\\n }\\n}\\n\\u003c/style\\u003e\\n\\u003cdiv + class=\\\"container\\\"\\u003e\\n \\u003cdiv class=\\\"headline\\\"\\u003e\\n + \ \\u003csvg class=\\\"logo-light\\\" width=\\\"18\\\" height=\\\"18\\\" + viewBox=\\\"9 9 35 35\\\" fill=\\\"none\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"\\u003e\\n + \ \\u003cpath fill-rule=\\\"evenodd\\\" clip-rule=\\\"evenodd\\\" d=\\\"M42.8622 + 27.0064C42.8622 25.7839 42.7525 24.6084 42.5487 23.4799H26.3109V30.1568H35.5897C35.1821 + 32.3041 33.9596 34.1222 32.1258 35.3448V39.6864H37.7213C40.9814 36.677 42.8622 + 32.2571 42.8622 27.0064V27.0064Z\\\" fill=\\\"#4285F4\\\"/\\u003e\\n \\u003cpath + fill-rule=\\\"evenodd\\\" clip-rule=\\\"evenodd\\\" d=\\\"M26.3109 43.8555C30.9659 + 43.8555 34.8687 42.3195 37.7213 39.6863L32.1258 35.3447C30.5898 36.3792 28.6306 + 37.0061 26.3109 37.0061C21.8282 37.0061 18.0195 33.9811 16.6559 29.906H10.9194V34.3573C13.7563 + 39.9841 19.5712 43.8555 26.3109 43.8555V43.8555Z\\\" fill=\\\"#34A853\\\"/\\u003e\\n + \ \\u003cpath fill-rule=\\\"evenodd\\\" clip-rule=\\\"evenodd\\\" d=\\\"M16.6559 + 29.8904C16.3111 28.8559 16.1074 27.7588 16.1074 26.6146C16.1074 25.4704 16.3111 + 24.3733 16.6559 23.3388V18.8875H10.9194C9.74388 21.2072 9.06992 23.8247 9.06992 + 26.6146C9.06992 29.4045 9.74388 32.022 10.9194 34.3417L15.3864 30.8621L16.6559 + 29.8904V29.8904Z\\\" fill=\\\"#FBBC05\\\"/\\u003e\\n \\u003cpath fill-rule=\\\"evenodd\\\" + clip-rule=\\\"evenodd\\\" d=\\\"M26.3109 16.2386C28.85 16.2386 31.107 17.1164 + 32.9095 18.8091L37.8466 13.8719C34.853 11.082 30.9659 9.3736 26.3109 9.3736C19.5712 + 9.3736 13.7563 13.245 10.9194 18.8875L16.6559 23.3388C18.0195 19.2636 21.8282 + 16.2386 26.3109 16.2386V16.2386Z\\\" fill=\\\"#EA4335\\\"/\\u003e\\n \\u003c/svg\\u003e\\n + \ \\u003csvg class=\\\"logo-dark\\\" width=\\\"18\\\" height=\\\"18\\\" + viewBox=\\\"0 0 48 48\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"\\u003e\\n + \ \\u003ccircle cx=\\\"24\\\" cy=\\\"23\\\" fill=\\\"#FFF\\\" r=\\\"22\\\"/\\u003e\\n + \ \\u003cpath d=\\\"M33.76 34.26c2.75-2.56 4.49-6.37 4.49-11.26 0-.89-.08-1.84-.29-3H24.01v5.99h8.03c-.4 + 2.02-1.5 3.56-3.07 4.56v.75l3.91 2.97h.88z\\\" fill=\\\"#4285F4\\\"/\\u003e\\n + \ \\u003cpath d=\\\"M15.58 25.77A8.845 8.845 0 0 0 24 31.86c1.92 0 3.62-.46 + 4.97-1.31l4.79 3.71C31.14 36.7 27.65 38 24 38c-5.93 0-11.01-3.4-13.45-8.36l.17-1.01 + 4.06-2.85h.8z\\\" fill=\\\"#34A853\\\"/\\u003e\\n \\u003cpath d=\\\"M15.59 + 20.21a8.864 8.864 0 0 0 0 5.58l-5.03 3.86c-.98-2-1.53-4.25-1.53-6.64 0-2.39.55-4.64 + 1.53-6.64l1-.22 3.81 2.98.22 1.08z\\\" fill=\\\"#FBBC05\\\"/\\u003e\\n \\u003cpath + d=\\\"M24 14.14c2.11 0 4.02.75 5.52 1.98l4.36-4.36C31.22 9.43 27.81 8 24 8c-5.93 + 0-11.01 3.4-13.45 8.36l5.03 3.85A8.86 8.86 0 0 1 24 14.14z\\\" fill=\\\"#EA4335\\\"/\\u003e\\n + \ \\u003c/svg\\u003e\\n \\u003cdiv class=\\\"gradient-container\\\"\\u003e\\u003cdiv + class=\\\"gradient\\\"\\u003e\\u003c/div\\u003e\\u003c/div\\u003e\\n \\u003c/div\\u003e\\n + \ \\u003cdiv class=\\\"carousel\\\"\\u003e\\n \\u003ca class=\\\"chip\\\" + href=\\\"https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQE75eSdvY972f3gk17-ltnPSn_fT3oGdUZUzeh5BmbuubDdtmayE5D_qhVVfxt0xzDYGEWwSYqTUknHYkxh4KqoXcugsloF1T3brrdsP9Ot6GiEs-lvoavkWlfNmog9vQVe7F9Q33-kDFmnguX11lct2m3s4XASwT-Co5rNXGBMIWCPi60uSyD2zAKBmZA0iLZxlvvY2pSM9UOt\\\"\\u003eggplot2 + release history\\u003c/a\\u003e\\n \\u003ca class=\\\"chip\\\" href=\\\"https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGSGekQqCaK1aOSrYxAiVrFEu-RzLE0TgQfMsxRhU5kmaBa2UloBVNjXVXFwXOraVNfHhVl0XfJL6W00kqSQAXzMGtMqtKPhEGTwJfe4HYk79nedjYFyL5g55qHO7IIscjDuRm4JYscp4U5QUSRDV0w-ZF8ioTngPjC5_x9fmPCKQOEe_b1504bnqgpLPmuDNboAowG7VGDRC6kazYQxEcNc-A=\\\"\\u003eggplot2 + 1.0.0 CRAN release date\\u003c/a\\u003e\\n \\u003c/div\\u003e\\n\\u003c/div\\u003e\\n\"},\"groundingChunks\": + [{\"web\": {\"uri\": \"https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQEjSNbji19KjF_gw6UFj3ZOC3mMjsKRoEV3fUpDEbRUR2lotH6MDj_eipDOvtSDLH_zzb7PzQbAGHzF32W-MKmU9mVYIDBh_qRW37-SyVsMycfRtcqVI0HwZ5qm\",\"title\": + \"rpkg.net\"}}],\"groundingSupports\": [{\"segment\": {\"startIndex\": 20,\"endIndex\": + 57,\"text\": \"0 was released to CRAN on 2014-05-21.\"},\"groundingChunkIndices\": + [0]}],\"webSearchQueries\": [\"ggplot2 1.0.0 CRAN release date\",\"ggplot2 + release history\"]}}],\"usageMetadata\": {\"promptTokenCount\": 27,\"candidatesTokenCount\": + 56,\"totalTokenCount\": 374,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": + 27}],\"toolUsePromptTokenCount\": 118,\"toolUsePromptTokensDetails\": [{\"modality\": + \"TEXT\",\"tokenCount\": 118}],\"thoughtsTokenCount\": 173},\"modelVersion\": + \"gemini-2.5-flash\",\"responseId\": \"UjVYabbAJpvUjMcPirW1qA0\"}\r\n\r\n" + headers: + Alt-Svc: + - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 + Content-Disposition: + - attachment + Content-Type: + - text/event-stream + Date: + - Fri, 02 Jan 2026 21:14:58 GMT + Server: + - scaffolding on HTTPServer2 + Server-Timing: + - gfet4t7; dur=2418 + Transfer-Encoding: + - chunked + Vary: + - Origin + - X-Origin + - Referer + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-XSS-Protection: + - '0' + status: + code: 200 + message: OK +- request: + body: '{"contents": [{"parts": [{"text": "When was ggplot2 1.0.0 released to CRAN? + Answer in YYYY-MM-DD format."}], "role": "user"}, {"parts": [{"text": "ggplot2 + version 1.0.0 was released to CRAN on 2014-05-21."}], "role": "model"}, {"parts": + [{"text": "What month was that?"}], "role": "user"}], "tools": [{"googleSearch": + {}}], "generationConfig": {"temperature": 0}}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '363' + Content-Type: + - application/json + Host: + - generativelanguage.googleapis.com + x-goog-api-client: + - google-genai-sdk/1.56.0 gl-python/3.12.11 + method: POST + uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse + response: + body: + string: "data: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"That + was May.\"}],\"role\": \"model\"},\"finishReason\": \"STOP\",\"index\": 0,\"groundingMetadata\": + {}}],\"usageMetadata\": {\"promptTokenCount\": 61,\"candidatesTokenCount\": + 4,\"totalTokenCount\": 113,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": + 61}],\"thoughtsTokenCount\": 48},\"modelVersion\": \"gemini-2.5-flash\",\"responseId\": + \"UzVYaey0I767_uMPlY_W6Q4\"}\r\n\r\n" + headers: + Alt-Svc: + - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 + Content-Disposition: + - attachment + Content-Type: + - text/event-stream + Date: + - Fri, 02 Jan 2026 21:14:59 GMT + Server: + - scaffolding on HTTPServer2 + Server-Timing: + - gfet4t7; dur=704 + Transfer-Encoding: + - chunked + Vary: + - Origin + - X-Origin + - Referer + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-XSS-Protection: + - '0' + status: + code: 200 + message: OK +version: 1 diff --git a/tests/_vcr/test_provider_openai/test_openai_web_search.yaml b/tests/_vcr/test_provider_openai/test_openai_web_search.yaml new file mode 100644 index 00000000..19cbebb6 --- /dev/null +++ b/tests/_vcr/test_provider_openai/test_openai_web_search.yaml @@ -0,0 +1,330 @@ +interactions: +- request: + body: '{"input": [{"role": "user", "content": [{"type": "input_text", "text": + "When was ggplot2 1.0.0 released to CRAN? Answer in YYYY-MM-DD format. The CRAN + archive page has this info."}]}], "model": "gpt-4.1", "store": false, "stream": + true, "tools": [{"type": "web_search"}]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '255' + Content-Type: + - application/json + Host: + - api.openai.com + X-Stainless-Async: + - 'false' + x-stainless-read-timeout: + - '600' + method: POST + uri: https://api.openai.com/v1/responses + response: + body: + string: "event: response.created\ndata: {\"type\":\"response.created\",\"sequence_number\":0,\"response\":{\"id\":\"resp_0b375c6deadb5c0101695834ac7f7c81a3a292a51a72d77608\",\"object\":\"response\",\"created_at\":1767388332,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"max_tool_calls\":null,\"model\":\"gpt-4.1-2025-04-14\",\"output\":[],\"parallel_tool_calls\":true,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":null,\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1.0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"web_search\",\"filters\":null,\"search_context_size\":\"medium\",\"user_location\":{\"type\":\"approximate\",\"city\":null,\"country\":\"US\",\"region\":null,\"timezone\":null}}],\"top_logprobs\":0,\"top_p\":1.0,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}}}\n\nevent: + response.in_progress\ndata: {\"type\":\"response.in_progress\",\"sequence_number\":1,\"response\":{\"id\":\"resp_0b375c6deadb5c0101695834ac7f7c81a3a292a51a72d77608\",\"object\":\"response\",\"created_at\":1767388332,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"max_tool_calls\":null,\"model\":\"gpt-4.1-2025-04-14\",\"output\":[],\"parallel_tool_calls\":true,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":null,\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1.0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"web_search\",\"filters\":null,\"search_context_size\":\"medium\",\"user_location\":{\"type\":\"approximate\",\"city\":null,\"country\":\"US\",\"region\":null,\"timezone\":null}}],\"top_logprobs\":0,\"top_p\":1.0,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}}}\n\nevent: + response.output_item.added\ndata: {\"type\":\"response.output_item.added\",\"sequence_number\":2,\"output_index\":0,\"item\":{\"id\":\"ws_0b375c6deadb5c0101695834ad3a5481a398eab6757caf8155\",\"type\":\"web_search_call\",\"status\":\"in_progress\",\"action\":{\"type\":\"search\"}}}\n\nevent: + response.web_search_call.in_progress\ndata: {\"type\":\"response.web_search_call.in_progress\",\"sequence_number\":3,\"output_index\":0,\"item_id\":\"ws_0b375c6deadb5c0101695834ad3a5481a398eab6757caf8155\"}\n\nevent: + response.web_search_call.searching\ndata: {\"type\":\"response.web_search_call.searching\",\"sequence_number\":4,\"output_index\":0,\"item_id\":\"ws_0b375c6deadb5c0101695834ad3a5481a398eab6757caf8155\"}\n\nevent: + response.web_search_call.completed\ndata: {\"type\":\"response.web_search_call.completed\",\"sequence_number\":5,\"output_index\":0,\"item_id\":\"ws_0b375c6deadb5c0101695834ad3a5481a398eab6757caf8155\"}\n\nevent: + response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"sequence_number\":6,\"output_index\":0,\"item\":{\"id\":\"ws_0b375c6deadb5c0101695834ad3a5481a398eab6757caf8155\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"search\",\"query\":\"ggplot2 + 1.0.0 CRAN archive release date\"}}}\n\nevent: response.output_item.added\ndata: + {\"type\":\"response.output_item.added\",\"sequence_number\":7,\"output_index\":1,\"item\":{\"id\":\"msg_0b375c6deadb5c0101695834aef55881a38062b7e3931eb744\",\"type\":\"message\",\"status\":\"in_progress\",\"content\":[],\"role\":\"assistant\"}}\n\nevent: + response.content_part.added\ndata: {\"type\":\"response.content_part.added\",\"sequence_number\":8,\"item_id\":\"msg_0b375c6deadb5c0101695834aef55881a38062b7e3931eb744\",\"output_index\":1,\"content_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"\"}}\n\nevent: + response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"sequence_number\":9,\"item_id\":\"msg_0b375c6deadb5c0101695834aef55881a38062b7e3931eb744\",\"output_index\":1,\"content_index\":0,\"delta\":\"The + version ggplot2\u202F1.0.0\",\"logprobs\":[],\"obfuscation\":\"rTXCezw\"}\n\nevent: + response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"sequence_number\":10,\"item_id\":\"msg_0b375c6deadb5c0101695834aef55881a38062b7e3931eb744\",\"output_index\":1,\"content_index\":0,\"delta\":\" + was released to CRAN (as seen in\",\"logprobs\":[],\"obfuscation\":\"JhYfAkP9THhghbM\"}\n\nevent: + response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"sequence_number\":11,\"item_id\":\"msg_0b375c6deadb5c0101695834aef55881a38062b7e3931eb744\",\"output_index\":1,\"content_index\":0,\"delta\":\" + the CRAN archive) on **2014\u201105\u2011\",\"logprobs\":[],\"obfuscation\":\"\"}\n\nevent: + response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"sequence_number\":12,\"item_id\":\"msg_0b375c6deadb5c0101695834aef55881a38062b7e3931eb744\",\"output_index\":1,\"content_index\":0,\"delta\":\"21**. + This is confirmed by the file listing showing:\\n\\n\",\"logprobs\":[],\"obfuscation\":\"5xe5rSB20W\"}\n\nevent: + response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"sequence_number\":13,\"item_id\":\"msg_0b375c6deadb5c0101695834aef55881a38062b7e3931eb744\",\"output_index\":1,\"content_index\":0,\"delta\":\"- + `ggplot2_1.0.0.tar\",\"logprobs\":[],\"obfuscation\":\"WwnzpWKnJvnO\"}\n\nevent: + response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"sequence_number\":14,\"item_id\":\"msg_0b375c6deadb5c0101695834aef55881a38062b7e3931eb744\",\"output_index\":1,\"content_index\":0,\"delta\":\".gz` + dated **2014\u201105\u201121**\",\"logprobs\":[],\"obfuscation\":\"YIXrsG8\"}\n\nevent: + response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"sequence_number\":15,\"item_id\":\"msg_0b375c6deadb5c0101695834aef55881a38062b7e3931eb744\",\"output_index\":1,\"content_index\":0,\"delta\":\" + \",\"logprobs\":[],\"obfuscation\":\"qr8Wsc4f61fcEzc\"}\n\nevent: response.output_text.delta\ndata: + {\"type\":\"response.output_text.delta\",\"sequence_number\":16,\"item_id\":\"msg_0b375c6deadb5c0101695834aef55881a38062b7e3931eb744\",\"output_index\":1,\"content_index\":0,\"delta\":\"([stat.ethz.ch](https://stat.ethz.ch/CRAN/src/contrib/Archive/ggplot2/?utm_source=openai)).\\n\\nTherefore, + the release date of gg\",\"logprobs\":[],\"obfuscation\":\"cu\"}\n\nevent: + response.output_text.annotation.added\ndata: {\"type\":\"response.output_text.annotation.added\",\"sequence_number\":17,\"item_id\":\"msg_0b375c6deadb5c0101695834aef55881a38062b7e3931eb744\",\"output_index\":1,\"content_index\":0,\"annotation_index\":0,\"annotation\":{\"type\":\"url_citation\",\"end_index\":280,\"start_index\":190,\"title\":\"Index + of /CRAN/src/contrib/Archive/ggplot2\",\"url\":\"https://stat.ethz.ch/CRAN/src/contrib/Archive/ggplot2/?utm_source=openai\"}}\n\nevent: + response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"sequence_number\":18,\"item_id\":\"msg_0b375c6deadb5c0101695834aef55881a38062b7e3931eb744\",\"output_index\":1,\"content_index\":0,\"delta\":\"plot2\u202F1.0.0 + on CRAN was **\",\"logprobs\":[],\"obfuscation\":\"EUITee\"}\n\nevent: response.output_text.delta\ndata: + {\"type\":\"response.output_text.delta\",\"sequence_number\":19,\"item_id\":\"msg_0b375c6deadb5c0101695834aef55881a38062b7e3931eb744\",\"output_index\":1,\"content_index\":0,\"delta\":\"2014\u201105\u201121**.\",\"logprobs\":[],\"obfuscation\":\"i0K\"}\n\nevent: + response.output_text.done\ndata: {\"type\":\"response.output_text.done\",\"sequence_number\":20,\"item_id\":\"msg_0b375c6deadb5c0101695834aef55881a38062b7e3931eb744\",\"output_index\":1,\"content_index\":0,\"text\":\"The + version ggplot2\u202F1.0.0 was released to CRAN (as seen in the CRAN archive) + on **2014\u201105\u201121**. This is confirmed by the file listing showing:\\n\\n- + `ggplot2_1.0.0.tar.gz` dated **2014\u201105\u201121** ([stat.ethz.ch](https://stat.ethz.ch/CRAN/src/contrib/Archive/ggplot2/?utm_source=openai)).\\n\\nTherefore, + the release date of ggplot2\u202F1.0.0 on CRAN was **2014\u201105\u201121**.\",\"logprobs\":[]}\n\nevent: + response.content_part.done\ndata: {\"type\":\"response.content_part.done\",\"sequence_number\":21,\"item_id\":\"msg_0b375c6deadb5c0101695834aef55881a38062b7e3931eb744\",\"output_index\":1,\"content_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[{\"type\":\"url_citation\",\"end_index\":280,\"start_index\":190,\"title\":\"Index + of /CRAN/src/contrib/Archive/ggplot2\",\"url\":\"https://stat.ethz.ch/CRAN/src/contrib/Archive/ggplot2/?utm_source=openai\"}],\"logprobs\":[],\"text\":\"The + version ggplot2\u202F1.0.0 was released to CRAN (as seen in the CRAN archive) + on **2014\u201105\u201121**. This is confirmed by the file listing showing:\\n\\n- + `ggplot2_1.0.0.tar.gz` dated **2014\u201105\u201121** ([stat.ethz.ch](https://stat.ethz.ch/CRAN/src/contrib/Archive/ggplot2/?utm_source=openai)).\\n\\nTherefore, + the release date of ggplot2\u202F1.0.0 on CRAN was **2014\u201105\u201121**.\"}}\n\nevent: + response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"sequence_number\":22,\"output_index\":1,\"item\":{\"id\":\"msg_0b375c6deadb5c0101695834aef55881a38062b7e3931eb744\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[{\"type\":\"url_citation\",\"end_index\":280,\"start_index\":190,\"title\":\"Index + of /CRAN/src/contrib/Archive/ggplot2\",\"url\":\"https://stat.ethz.ch/CRAN/src/contrib/Archive/ggplot2/?utm_source=openai\"}],\"logprobs\":[],\"text\":\"The + version ggplot2\u202F1.0.0 was released to CRAN (as seen in the CRAN archive) + on **2014\u201105\u201121**. This is confirmed by the file listing showing:\\n\\n- + `ggplot2_1.0.0.tar.gz` dated **2014\u201105\u201121** ([stat.ethz.ch](https://stat.ethz.ch/CRAN/src/contrib/Archive/ggplot2/?utm_source=openai)).\\n\\nTherefore, + the release date of ggplot2\u202F1.0.0 on CRAN was **2014\u201105\u201121**.\"}],\"role\":\"assistant\"}}\n\nevent: + response.completed\ndata: {\"type\":\"response.completed\",\"sequence_number\":23,\"response\":{\"id\":\"resp_0b375c6deadb5c0101695834ac7f7c81a3a292a51a72d77608\",\"object\":\"response\",\"created_at\":1767388332,\"status\":\"completed\",\"background\":false,\"completed_at\":1767388335,\"error\":null,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"max_tool_calls\":null,\"model\":\"gpt-4.1-2025-04-14\",\"output\":[{\"id\":\"ws_0b375c6deadb5c0101695834ad3a5481a398eab6757caf8155\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"search\",\"query\":\"ggplot2 + 1.0.0 CRAN archive release date\"}},{\"id\":\"msg_0b375c6deadb5c0101695834aef55881a38062b7e3931eb744\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[{\"type\":\"url_citation\",\"end_index\":280,\"start_index\":190,\"title\":\"Index + of /CRAN/src/contrib/Archive/ggplot2\",\"url\":\"https://stat.ethz.ch/CRAN/src/contrib/Archive/ggplot2/?utm_source=openai\"}],\"logprobs\":[],\"text\":\"The + version ggplot2\u202F1.0.0 was released to CRAN (as seen in the CRAN archive) + on **2014\u201105\u201121**. This is confirmed by the file listing showing:\\n\\n- + `ggplot2_1.0.0.tar.gz` dated **2014\u201105\u201121** ([stat.ethz.ch](https://stat.ethz.ch/CRAN/src/contrib/Archive/ggplot2/?utm_source=openai)).\\n\\nTherefore, + the release date of ggplot2\u202F1.0.0 on CRAN was **2014\u201105\u201121**.\"}],\"role\":\"assistant\"}],\"parallel_tool_calls\":true,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":null,\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":false,\"temperature\":1.0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"web_search\",\"filters\":null,\"search_context_size\":\"medium\",\"user_location\":{\"type\":\"approximate\",\"city\":null,\"country\":\"US\",\"region\":null,\"timezone\":null}}],\"top_logprobs\":0,\"top_p\":1.0,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":16789,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":149,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":16938},\"user\":null,\"metadata\":{}}}\n\n" + headers: + CF-RAY: + - 9b7d40d2e8061aeb-ORD + Connection: + - keep-alive + Content-Type: + - text/event-stream; charset=utf-8 + Date: + - Fri, 02 Jan 2026 21:12:12 GMT + Server: + - cloudflare + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + alt-svc: + - h3=":443"; ma=86400 + cf-cache-status: + - DYNAMIC + openai-processing-ms: + - '80' + openai-version: + - '2020-10-01' + x-envoy-upstream-service-time: + - '84' + status: + code: 200 + message: OK +- request: + body: '{"input": [{"role": "user", "content": [{"type": "input_text", "text": + "When was ggplot2 1.0.0 released to CRAN? Answer in YYYY-MM-DD format. The CRAN + archive page has this info."}]}, {"id": "ws_0b375c6deadb5c0101695834ad3a5481a398eab6757caf8155", + "action": {"query": "ggplot2 1.0.0 CRAN archive release date", "type": "search", + "sources": null}, "status": "completed", "type": "web_search_call"}, {"role": + "assistant", "content": [{"type": "output_text", "text": "The version ggplot2\u202f1.0.0 + was released to CRAN (as seen in the CRAN archive) on **2014\u201105\u201121**. + This is confirmed by the file listing showing:\n\n- `ggplot2_1.0.0.tar.gz` dated + **2014\u201105\u201121** ([stat.ethz.ch](https://stat.ethz.ch/CRAN/src/contrib/Archive/ggplot2/?utm_source=openai)).\n\nTherefore, + the release date of ggplot2\u202f1.0.0 on CRAN was **2014\u201105\u201121**.", + "annotations": []}], "status": "completed", "type": "message", "id": "msg_missing_id"}, + {"role": "user", "content": [{"type": "input_text", "text": "What month was + that?"}]}], "model": "gpt-4.1", "store": false, "stream": true, "tools": [{"type": + "web_search"}]}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1054' + Content-Type: + - application/json + Cookie: + - __cf_bm=Ch7saxZv7YFT6J1zys.im44XNplchCclx2B4q.rjVdY-1767388332-1.0.1.1-MXgkBIZwfl6crDFKks3g9hE9Be4yfEV3MN9ZTBLWfLoCnQWpZeOBv0cp9qxQdALFEwePA_bbx4XJoDB_aXtvakhIvglD3QwajLuho_W9300; + _cfuvid=HIAsTJ5UoVLDp.CxfI_FvHln86lcpaWE2tBU.KKx1FQ-1767388332588-0.0.1.1-604800000 + Host: + - api.openai.com + X-Stainless-Async: + - 'false' + x-stainless-read-timeout: + - '600' + method: POST + uri: https://api.openai.com/v1/responses + response: + body: + string: 'event: response.created + + data: {"type":"response.created","sequence_number":0,"response":{"id":"resp_0b375c6deadb5c0101695834b0801881a3bb8a03201711d867","object":"response","created_at":1767388336,"status":"in_progress","background":false,"completed_at":null,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"gpt-4.1-2025-04-14","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"prompt_cache_retention":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[{"type":"web_search","filters":null,"search_context_size":"medium","user_location":{"type":"approximate","city":null,"country":"US","region":null,"timezone":null}}],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}} + + + event: response.in_progress + + data: {"type":"response.in_progress","sequence_number":1,"response":{"id":"resp_0b375c6deadb5c0101695834b0801881a3bb8a03201711d867","object":"response","created_at":1767388336,"status":"in_progress","background":false,"completed_at":null,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"gpt-4.1-2025-04-14","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"prompt_cache_retention":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[{"type":"web_search","filters":null,"search_context_size":"medium","user_location":{"type":"approximate","city":null,"country":"US","region":null,"timezone":null}}],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}} + + + event: response.output_item.added + + data: {"type":"response.output_item.added","sequence_number":2,"output_index":0,"item":{"id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","type":"message","status":"in_progress","content":[],"role":"assistant"}} + + + event: response.content_part.added + + data: {"type":"response.content_part.added","sequence_number":3,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":""}} + + + event: response.output_text.delta + + data: {"type":"response.output_text.delta","sequence_number":4,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"delta":"The","logprobs":[],"obfuscation":"etX0SC2Mjg0hf"} + + + event: response.output_text.delta + + data: {"type":"response.output_text.delta","sequence_number":5,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"delta":" + date","logprobs":[],"obfuscation":"5vfDUZLCqrK"} + + + event: response.output_text.delta + + data: {"type":"response.output_text.delta","sequence_number":6,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"delta":" + **","logprobs":[],"obfuscation":"II6Dpr3nYr1Xh"} + + + event: response.output_text.delta + + data: {"type":"response.output_text.delta","sequence_number":7,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"delta":"201","logprobs":[],"obfuscation":"BsnXjNKi96Q8W"} + + + event: response.output_text.delta + + data: {"type":"response.output_text.delta","sequence_number":8,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"delta":"4","logprobs":[],"obfuscation":"zhdk0lLYIMqp4al"} + + + event: response.output_text.delta + + data: {"type":"response.output_text.delta","sequence_number":9,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"delta":"-","logprobs":[],"obfuscation":"vxFIKr93xmhMt7W"} + + + event: response.output_text.delta + + data: {"type":"response.output_text.delta","sequence_number":10,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"delta":"05","logprobs":[],"obfuscation":"inHeBOnt4rHPdq"} + + + event: response.output_text.delta + + data: {"type":"response.output_text.delta","sequence_number":11,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"delta":"-","logprobs":[],"obfuscation":"JP7bIRMDJryUsM8"} + + + event: response.output_text.delta + + data: {"type":"response.output_text.delta","sequence_number":12,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"delta":"21","logprobs":[],"obfuscation":"mmN4ZogyrdYfpx"} + + + event: response.output_text.delta + + data: {"type":"response.output_text.delta","sequence_number":13,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"delta":"**","logprobs":[],"obfuscation":"Vd2VlOSUFXGBqn"} + + + event: response.output_text.delta + + data: {"type":"response.output_text.delta","sequence_number":14,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"delta":" + is","logprobs":[],"obfuscation":"xeLwUo8pDJH9T"} + + + event: response.output_text.delta + + data: {"type":"response.output_text.delta","sequence_number":15,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"delta":" + in","logprobs":[],"obfuscation":"d0aTYP8COC67h"} + + + event: response.output_text.delta + + data: {"type":"response.output_text.delta","sequence_number":16,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"delta":" + the","logprobs":[],"obfuscation":"LdW8VTRXB17Z"} + + + event: response.output_text.delta + + data: {"type":"response.output_text.delta","sequence_number":17,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"delta":" + month","logprobs":[],"obfuscation":"ammCFujzz7"} + + + event: response.output_text.delta + + data: {"type":"response.output_text.delta","sequence_number":18,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"delta":" + of","logprobs":[],"obfuscation":"YfRbagihAaEgO"} + + + event: response.output_text.delta + + data: {"type":"response.output_text.delta","sequence_number":19,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"delta":" + **","logprobs":[],"obfuscation":"nMiwlpVUcTfoH"} + + + event: response.output_text.delta + + data: {"type":"response.output_text.delta","sequence_number":20,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"delta":"May","logprobs":[],"obfuscation":"RCAGKsFcBNJ3x"} + + + event: response.output_text.delta + + data: {"type":"response.output_text.delta","sequence_number":21,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"delta":"**","logprobs":[],"obfuscation":"trQUp4ZGiNDt05"} + + + event: response.output_text.delta + + data: {"type":"response.output_text.delta","sequence_number":22,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"delta":".","logprobs":[],"obfuscation":"fKh9lKtWkxISKHE"} + + + event: response.output_text.done + + data: {"type":"response.output_text.done","sequence_number":23,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"text":"The + date **2014-05-21** is in the month of **May**.","logprobs":[]} + + + event: response.content_part.done + + data: {"type":"response.content_part.done","sequence_number":24,"item_id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","output_index":0,"content_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":"The + date **2014-05-21** is in the month of **May**."}} + + + event: response.output_item.done + + data: {"type":"response.output_item.done","sequence_number":25,"output_index":0,"item":{"id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","type":"message","status":"completed","content":[{"type":"output_text","annotations":[],"logprobs":[],"text":"The + date **2014-05-21** is in the month of **May**."}],"role":"assistant"}} + + + event: response.completed + + data: {"type":"response.completed","sequence_number":26,"response":{"id":"resp_0b375c6deadb5c0101695834b0801881a3bb8a03201711d867","object":"response","created_at":1767388336,"status":"completed","background":false,"completed_at":1767388337,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"gpt-4.1-2025-04-14","output":[{"id":"msg_0b375c6deadb5c0101695834b1102481a39d18a9a7f76d5463","type":"message","status":"completed","content":[{"type":"output_text","annotations":[],"logprobs":[],"text":"The + date **2014-05-21** is in the month of **May**."}],"role":"assistant"}],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"prompt_cache_retention":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"default","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[{"type":"web_search","filters":null,"search_context_size":"medium","user_location":{"type":"approximate","city":null,"country":"US","region":null,"timezone":null}}],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":{"input_tokens":472,"input_tokens_details":{"cached_tokens":0},"output_tokens":21,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":493},"user":null,"metadata":{}}} + + + ' + headers: + CF-RAY: + - 9b7d40ebfc8ef939-ORD + Connection: + - keep-alive + Content-Type: + - text/event-stream; charset=utf-8 + Date: + - Fri, 02 Jan 2026 21:12:16 GMT + Server: + - cloudflare + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + alt-svc: + - h3=":443"; ma=86400 + cf-cache-status: + - DYNAMIC + openai-processing-ms: + - '49' + openai-version: + - '2020-10-01' + x-envoy-upstream-service-time: + - '53' + status: + code: 200 + message: OK +version: 1 diff --git a/tests/conftest.py b/tests/conftest.py index 7cf0dc09..c9ef4092 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -381,6 +381,42 @@ def assert_list_models(chat_fun: ChatFun): assert "id" in models[0] +# --------------------------------------------------------------------------- +# Built-in tools (web search/fetch) +# --------------------------------------------------------------------------- + + +def assert_tool_web_fetch(chat_fun: ChatFun, tool, stream: bool = True): + """Test web fetch tool functionality.""" + chat = chat_fun() + chat.register_tool(tool) + + url = "https://rvest.tidyverse.org/articles/starwars.html" + response = chat.chat(f"What's the first movie listed on {url}?", stream=stream) + assert "The Phantom Menace" in str(response) + + response = chat.chat("Who directed it?", stream=stream) + assert "George Lucas" in str(response) + + +def assert_tool_web_search(chat_fun: ChatFun, tool, hint: str = "", stream: bool = True): + """Test web search tool functionality.""" + chat = chat_fun() + chat.register_tool(tool) + + prompt = "When was ggplot2 1.0.0 released to CRAN? Answer in YYYY-MM-DD format." + if hint: + prompt += f" {hint}" + + response = chat.chat(prompt, stream=stream) + # Replace non-breaking hyphens with regular hyphens (for OpenAI) + result = str(response).replace("\u2011", "-") + assert "2014-05-21" in result + + response = chat.chat("What month was that?", stream=stream) + assert "May" in str(response) + + retry_api_call = retry( wait=wait_exponential(min=1, max=60), stop=stop_after_attempt(3), diff --git a/tests/test_provider_anthropic.py b/tests/test_provider_anthropic.py index b7729e7b..73ef2447 100644 --- a/tests/test_provider_anthropic.py +++ b/tests/test_provider_anthropic.py @@ -2,10 +2,16 @@ import httpx import pytest -from pydantic import BaseModel, Field - -from chatlas import AssistantTurn, ChatAnthropic, UserTurn, content_image_file +from chatlas import ( + AssistantTurn, + ChatAnthropic, + UserTurn, + content_image_file, + tool_web_fetch, + tool_web_search, +) from chatlas._provider_anthropic import AnthropicProvider +from pydantic import BaseModel, Field from .conftest import ( assert_data_extraction, @@ -13,6 +19,8 @@ assert_images_remote, assert_list_models, assert_pdf_local, + assert_tool_web_fetch, + assert_tool_web_search, assert_tools_async, assert_tools_parallel, assert_tools_sequential, @@ -87,6 +95,48 @@ async def test_anthropic_tool_variations_async(): await assert_tools_async(chat_func) +@pytest.mark.vcr +def test_anthropic_web_fetch(): + def chat_fun(**kwargs): + return ChatAnthropic( + model="claude-haiku-4-5-20251001", + kwargs={"default_headers": {"anthropic-beta": "web-fetch-2025-09-10"}}, + **kwargs, + ) + + assert_tool_web_fetch(chat_fun, tool_web_fetch()) + + +@pytest.mark.vcr +def test_anthropic_web_search(): + assert_tool_web_search(chat_func, tool_web_search()) + + +@pytest.mark.vcr +def test_anthropic_web_search_citations(): + """Test that citations from web search are preserved on the completion.""" + chat = chat_func() + chat.register_tool(tool_web_search()) + chat.chat( + "When was ggplot2 1.0.0 released to CRAN? Answer in YYYY-MM-DD format." + ) + + # Get the turn and verify citations are on the completion + turn = chat.get_last_turn() + assert turn is not None + assert turn.completion is not None + + # Find a text content block that should have citations + text_blocks = [c for c in turn.completion.content if c.type == "text"] + assert len(text_blocks) > 0 + + # At least one text block should have citations from web search + has_citations = any( + getattr(block, "citations", None) for block in text_blocks + ) + assert has_citations, "Expected citations on text blocks from web search" + + @pytest.mark.vcr def test_data_extraction(): assert_data_extraction(chat_func) diff --git a/tests/test_provider_google.py b/tests/test_provider_google.py index ae2cf0fe..7aae8bb6 100644 --- a/tests/test_provider_google.py +++ b/tests/test_provider_google.py @@ -1,6 +1,6 @@ import pytest import requests -from chatlas import ChatGoogle, ChatVertex +from chatlas import ChatGoogle, ChatVertex, tool_web_fetch, tool_web_search from google.genai.errors import APIError from tenacity import retry, retry_if_exception, stop_after_attempt, wait_exponential @@ -10,6 +10,8 @@ assert_images_remote_error, assert_list_models, assert_pdf_local, + assert_tool_web_fetch, + assert_tool_web_search, assert_tools_parallel, assert_tools_sequential, assert_tools_simple, @@ -153,6 +155,18 @@ def test_data_extraction(): assert_data_extraction(chat_func) +@pytest.mark.vcr +@retry_gemini_call +def test_google_web_fetch(): + assert_tool_web_fetch(chat_func, tool_web_fetch()) + + +@pytest.mark.vcr +@retry_gemini_call +def test_google_web_search(): + assert_tool_web_search(chat_func, tool_web_search()) + + @pytest.mark.vcr @retry_gemini_call def test_images_inline(): diff --git a/tests/test_provider_openai.py b/tests/test_provider_openai.py index ee907075..953b1309 100644 --- a/tests/test_provider_openai.py +++ b/tests/test_provider_openai.py @@ -1,6 +1,6 @@ import httpx import pytest -from chatlas import ChatOpenAI +from chatlas import ChatOpenAI, tool_web_search from openai.types.responses import ResponseOutputMessage, ResponseOutputText from .conftest import ( @@ -9,6 +9,7 @@ assert_images_remote, assert_list_models, assert_pdf_local, + assert_tool_web_search, assert_tools_async, assert_tools_parallel, assert_tools_sequential, @@ -74,6 +75,18 @@ def test_data_extraction(): assert_data_extraction(ChatOpenAI) +@pytest.mark.vcr +def test_openai_web_search(): + def chat_fun(**kwargs): + return ChatOpenAI(model="gpt-4.1", **kwargs) + + assert_tool_web_search( + chat_fun, + tool_web_search(), + hint="The CRAN archive page has this info.", + ) + + @pytest.mark.vcr def test_openai_images(): chat_fun = ChatOpenAI diff --git a/tests/test_tools_builtin.py b/tests/test_tools_builtin.py new file mode 100644 index 00000000..050ab3ec --- /dev/null +++ b/tests/test_tools_builtin.py @@ -0,0 +1,332 @@ +"""Tests for built-in web search and fetch tools.""" + +import pytest + +from chatlas import ( + ChatAnthropic, + ChatGoogle, + ChatOpenAI, + tool_web_fetch, + tool_web_search, +) +from chatlas._tools_builtin import ToolWebFetch, ToolWebSearch + + +class TestToolWebSearchConfiguration: + """Test ToolWebSearch configuration and validation.""" + + def test_basic_configuration(self): + """Test creating a basic web search tool.""" + tool = tool_web_search() + assert isinstance(tool, ToolWebSearch) + assert tool.name == "web_search" + assert tool.allowed_domains is None + assert tool.blocked_domains is None + assert tool.user_location is None + assert tool.max_uses is None + + def test_with_allowed_domains(self): + """Test web search tool with allowed domains.""" + tool = tool_web_search(allowed_domains=["nytimes.com", "bbc.com"]) + assert tool.allowed_domains == ["nytimes.com", "bbc.com"] + assert tool.blocked_domains is None + + def test_with_blocked_domains(self): + """Test web search tool with blocked domains.""" + tool = tool_web_search(blocked_domains=["spam.com"]) + assert tool.blocked_domains == ["spam.com"] + assert tool.allowed_domains is None + + def test_cannot_use_both_domain_filters(self): + """Test that both allowed and blocked domains cannot be specified.""" + with pytest.raises( + ValueError, match="Cannot specify both allowed_domains and blocked_domains" + ): + tool_web_search( + allowed_domains=["good.com"], blocked_domains=["bad.com"] + ) + + def test_with_user_location(self): + """Test web search tool with user location.""" + location = { + "country": "US", + "city": "San Francisco", + "region": "California", + "timezone": "America/Los_Angeles", + } + tool = tool_web_search(user_location=location) + assert tool.user_location == location + + def test_with_max_uses(self): + """Test web search tool with max uses.""" + tool = tool_web_search(max_uses=5) + assert tool.max_uses == 5 + + +class TestToolWebFetchConfiguration: + """Test ToolWebFetch configuration and validation.""" + + def test_basic_configuration(self): + """Test creating a basic web fetch tool.""" + tool = tool_web_fetch() + assert isinstance(tool, ToolWebFetch) + assert tool.name == "web_fetch" + assert tool.allowed_domains is None + assert tool.blocked_domains is None + assert tool.max_uses is None + + def test_with_allowed_domains(self): + """Test web fetch tool with allowed domains.""" + tool = tool_web_fetch(allowed_domains=["example.com"]) + assert tool.allowed_domains == ["example.com"] + + def test_cannot_use_both_domain_filters(self): + """Test that both allowed and blocked domains cannot be specified.""" + with pytest.raises( + ValueError, match="Cannot specify both allowed_domains and blocked_domains" + ): + tool_web_fetch( + allowed_domains=["good.com"], blocked_domains=["bad.com"] + ) + + +class TestToolWebSearchProviderDefinitions: + """Test that provider-specific definitions are generated correctly.""" + + def test_openai_basic_definition(self): + """Test OpenAI definition for basic web search.""" + tool = tool_web_search() + definition = tool.get_definition("openai") + assert definition["type"] == "web_search" + + def test_openai_with_allowed_domains(self): + """Test OpenAI definition with allowed domains.""" + tool = tool_web_search(allowed_domains=["https://nytimes.com", "bbc.com"]) + definition = tool.get_definition("openai") + assert definition["type"] == "web_search" + # Should strip http/https prefixes + assert definition["filters"]["allowed_domains"] == ["nytimes.com", "bbc.com"] + + def test_openai_with_user_location(self): + """Test OpenAI definition with user location.""" + tool = tool_web_search(user_location={"country": "US", "city": "NYC"}) + definition = tool.get_definition("openai") + assert definition["user_location"]["type"] == "approximate" + assert definition["user_location"]["country"] == "US" + assert definition["user_location"]["city"] == "NYC" + + def test_anthropic_basic_definition(self): + """Test Anthropic definition for basic web search.""" + tool = tool_web_search() + definition = tool.get_definition("anthropic") + assert definition["name"] == "web_search" + assert definition["type"] == "web_search_20250305" + + def test_anthropic_with_all_options(self): + """Test Anthropic definition with all options.""" + tool = tool_web_search( + allowed_domains=["nytimes.com"], + user_location={"country": "US"}, + max_uses=10, + ) + definition = tool.get_definition("anthropic") + assert definition["allowed_domains"] == ["nytimes.com"] + assert definition["user_location"] == {"type": "approximate", "country": "US"} + assert definition["max_uses"] == 10 + + def test_anthropic_with_blocked_domains(self): + """Test Anthropic definition with blocked domains.""" + tool = tool_web_search(blocked_domains=["spam.com"]) + definition = tool.get_definition("anthropic") + assert definition["blocked_domains"] == ["spam.com"] + + def test_google_definition(self): + """Test Google definition for web search.""" + from google.genai.types import GoogleSearch + + tool = tool_web_search() + definition = tool.get_definition("google") + assert isinstance(definition, GoogleSearch) + + def test_google_with_blocked_domains(self): + """Test Google definition with blocked domains.""" + tool = tool_web_search(blocked_domains=["spam.com", "ads.com"]) + definition = tool.get_definition("google") + assert definition.exclude_domains == ["spam.com", "ads.com"] + + def test_unsupported_provider(self): + """Test that unsupported provider raises error.""" + tool = tool_web_search() + with pytest.raises(ValueError, match="Web search is not supported"): + tool.get_definition("unsupported_provider") + + def test_openai_warns_on_unsupported_params(self): + """Test that OpenAI warns about unsupported parameters.""" + tool = tool_web_search(blocked_domains=["spam.com"], max_uses=5) + with pytest.warns(UserWarning, match="blocked_domains is not supported by OpenAI"): + tool.get_definition("openai") + + def test_google_warns_on_unsupported_params(self): + """Test that Google warns about unsupported parameters.""" + tool = tool_web_search( + allowed_domains=["example.com"], + user_location={"country": "US"}, + max_uses=5, + ) + with pytest.warns(UserWarning) as record: + tool.get_definition("google") + messages = [str(w.message) for w in record] + assert any("allowed_domains" in m for m in messages) + assert any("user_location" in m for m in messages) + assert any("max_uses" in m for m in messages) + + def test_openai_with_search_context_size(self): + """Test that OpenAI definition accepts search_context_size parameter.""" + tool = tool_web_search() + definition = tool.get_definition("openai", search_context_size="high") + assert definition["search_context_size"] == "high" + + def test_anthropic_with_cache_control(self): + """Test that Anthropic definition accepts cache_control parameter.""" + tool = tool_web_search() + definition = tool.get_definition( + "anthropic", cache_control={"type": "ephemeral"} + ) + assert definition["cache_control"] == {"type": "ephemeral"} + + +class TestToolWebFetchProviderDefinitions: + """Test that provider-specific fetch definitions are generated correctly.""" + + def test_anthropic_basic_definition(self): + """Test Anthropic definition for basic web fetch.""" + tool = tool_web_fetch() + definition = tool.get_definition("anthropic") + assert definition["name"] == "web_fetch" + assert definition["type"] == "web_fetch_20250910" + + def test_anthropic_with_all_options(self): + """Test Anthropic definition with all options.""" + tool = tool_web_fetch( + allowed_domains=["example.com"], + max_uses=5, + ) + definition = tool.get_definition("anthropic") + assert definition["allowed_domains"] == ["example.com"] + assert definition["max_uses"] == 5 + + def test_google_definition(self): + """Test Google definition for web fetch.""" + from google.genai.types import UrlContext + + tool = tool_web_fetch() + definition = tool.get_definition("google") + assert isinstance(definition, UrlContext) + + def test_openai_not_supported(self): + """Test that OpenAI raises error for web fetch.""" + tool = tool_web_fetch() + with pytest.raises(ValueError, match="Web fetch is not supported"): + tool.get_definition("openai") + + def test_google_warns_on_unsupported_params(self): + """Test that Google warns about unsupported parameters.""" + tool = tool_web_fetch( + allowed_domains=["example.com"], + blocked_domains=None, + max_uses=5, + ) + # Reset to test blocked_domains separately + tool2 = tool_web_fetch(blocked_domains=["spam.com"]) + + with pytest.warns(UserWarning) as record: + tool.get_definition("google") + messages = [str(w.message) for w in record] + assert any("allowed_domains" in m for m in messages) + assert any("max_uses" in m for m in messages) + + with pytest.warns(UserWarning, match="blocked_domains is not supported by Google"): + tool2.get_definition("google") + + def test_anthropic_with_extra_params(self): + """Test that Anthropic definition accepts provider-specific parameters.""" + tool = tool_web_fetch() + definition = tool.get_definition( + "anthropic", + cache_control={"type": "ephemeral"}, + max_content_tokens=1000, + ) + assert definition["cache_control"] == {"type": "ephemeral"} + assert definition["max_content_tokens"] == 1000 + + +class TestChatRegistration: + """Test registering web search tools with chat instances.""" + + def test_register_web_search_openai(self): + """Test registering web search tool with OpenAI chat.""" + chat = ChatOpenAI() + tool = tool_web_search() + chat.register_tool(tool) + + tools = chat.get_tools() + assert len(tools) == 1 + assert tools[0].name == "web_search" + assert isinstance(tools[0], ToolWebSearch) + + def test_register_web_search_anthropic(self): + """Test registering web search tool with Anthropic chat.""" + chat = ChatAnthropic() + tool = tool_web_search() + chat.register_tool(tool) + + tools = chat.get_tools() + assert len(tools) == 1 + assert tools[0].name == "web_search" + + def test_register_web_search_google(self): + """Test registering web search tool with Google chat.""" + chat = ChatGoogle() + tool = tool_web_search() + chat.register_tool(tool) + + tools = chat.get_tools() + assert len(tools) == 1 + assert tools[0].name == "web_search" + + def test_register_web_fetch_anthropic(self): + """Test registering web fetch tool with Anthropic chat.""" + chat = ChatAnthropic() + tool = tool_web_fetch() + chat.register_tool(tool) + + tools = chat.get_tools() + assert len(tools) == 1 + assert tools[0].name == "web_fetch" + + def test_register_multiple_builtin_tools(self): + """Test registering multiple built-in tools.""" + chat = ChatAnthropic() + chat.register_tool(tool_web_search()) + chat.register_tool(tool_web_fetch()) + + tools = chat.get_tools() + assert len(tools) == 2 + tool_names = {t.name for t in tools} + assert tool_names == {"web_search", "web_fetch"} + + def test_register_builtin_and_regular_tools(self): + """Test registering both built-in and regular tools.""" + chat = ChatOpenAI() + + def add(x: int, y: int) -> int: + """Add two numbers.""" + return x + y + + chat.register_tool(tool_web_search()) + chat.register_tool(add) + + tools = chat.get_tools() + assert len(tools) == 2 + tool_names = {t.name for t in tools} + assert tool_names == {"web_search", "add"}