|
13 | 13 | from .. import ModelHTTPError, UnexpectedModelBehavior, _utils, usage |
14 | 14 | from .._run_context import RunContext |
15 | 15 | from .._utils import guard_tool_call_id as _guard_tool_call_id |
16 | | -from ..builtin_tools import CodeExecutionTool, MCPServerTool, MemoryTool, WebSearchTool |
| 16 | +from ..builtin_tools import CodeExecutionTool, MCPServerTool, MemoryTool, UrlContextTool, WebSearchTool |
17 | 17 | from ..exceptions import UserError |
18 | 18 | from ..messages import ( |
19 | 19 | BinaryContent, |
|
106 | 106 | BetaToolUnionParam, |
107 | 107 | BetaToolUseBlock, |
108 | 108 | BetaToolUseBlockParam, |
| 109 | + BetaWebFetchTool20250910Param, |
| 110 | + BetaWebFetchToolResultBlock, |
| 111 | + BetaWebFetchToolResultBlockParam, |
109 | 112 | BetaWebSearchTool20250305Param, |
110 | 113 | BetaWebSearchToolResultBlock, |
111 | 114 | BetaWebSearchToolResultBlockContent, |
@@ -371,6 +374,8 @@ def _process_response(self, response: BetaMessage) -> ModelResponse: |
371 | 374 | items.append(_map_web_search_tool_result_block(item, self.system)) |
372 | 375 | elif isinstance(item, BetaCodeExecutionToolResultBlock): |
373 | 376 | items.append(_map_code_execution_tool_result_block(item, self.system)) |
| 377 | + elif isinstance(item, BetaWebFetchToolResultBlock): |
| 378 | + items.append(_map_web_fetch_tool_result_block(item, self.system)) |
374 | 379 | elif isinstance(item, BetaRedactedThinkingBlock): |
375 | 380 | items.append( |
376 | 381 | ThinkingPart(id='redacted_thinking', content='', signature=item.data, provider_name=self.system) |
@@ -464,6 +469,9 @@ def _add_builtin_tools( |
464 | 469 | elif isinstance(tool, CodeExecutionTool): # pragma: no branch |
465 | 470 | tools.append(BetaCodeExecutionTool20250522Param(name='code_execution', type='code_execution_20250522')) |
466 | 471 | beta_features.append('code-execution-2025-05-22') |
| 472 | + elif isinstance(tool, UrlContextTool): # pragma: no branch |
| 473 | + tools.append(BetaWebFetchTool20250910Param(name='web_fetch', type='web_fetch_20250910')) |
| 474 | + beta_features.append('web-fetch-2025-09-10') |
467 | 475 | elif isinstance(tool, MemoryTool): # pragma: no branch |
468 | 476 | if 'memory' not in model_request_parameters.tool_defs: |
469 | 477 | raise UserError("Built-in `MemoryTool` requires a 'memory' tool to be defined.") |
@@ -542,6 +550,7 @@ async def _map_message( # noqa: C901 |
542 | 550 | | BetaServerToolUseBlockParam |
543 | 551 | | BetaWebSearchToolResultBlockParam |
544 | 552 | | BetaCodeExecutionToolResultBlockParam |
| 553 | + | BetaWebFetchToolResultBlockParam |
545 | 554 | | BetaThinkingBlockParam |
546 | 555 | | BetaRedactedThinkingBlockParam |
547 | 556 | | BetaMCPToolUseBlockParam |
@@ -604,6 +613,14 @@ async def _map_message( # noqa: C901 |
604 | 613 | input=response_part.args_as_dict(), |
605 | 614 | ) |
606 | 615 | assistant_content_params.append(server_tool_use_block_param) |
| 616 | + elif response_part.tool_name == UrlContextTool.kind: |
| 617 | + server_tool_use_block_param = BetaServerToolUseBlockParam( |
| 618 | + id=tool_use_id, |
| 619 | + type='server_tool_use', |
| 620 | + name='web_fetch', |
| 621 | + input=response_part.args_as_dict(), |
| 622 | + ) |
| 623 | + assistant_content_params.append(server_tool_use_block_param) |
607 | 624 | elif ( |
608 | 625 | response_part.tool_name.startswith(MCPServerTool.kind) |
609 | 626 | and (server_id := response_part.tool_name.split(':', 1)[1]) |
@@ -650,6 +667,19 @@ async def _map_message( # noqa: C901 |
650 | 667 | ), |
651 | 668 | ) |
652 | 669 | ) |
| 670 | + elif response_part.tool_name == UrlContextTool.kind and isinstance( |
| 671 | + response_part.content, dict |
| 672 | + ): # pragma: no branch |
| 673 | + assistant_content_params.append( |
| 674 | + cast( |
| 675 | + BetaWebFetchToolResultBlockParam, |
| 676 | + { |
| 677 | + 'tool_use_id': tool_use_id, |
| 678 | + 'type': 'web_fetch_tool_result', |
| 679 | + 'content': response_part.content, # pyright: ignore[reportUnknownMemberType] |
| 680 | + }, |
| 681 | + ) |
| 682 | + ) |
653 | 683 | elif response_part.tool_name.startswith(MCPServerTool.kind) and isinstance( |
654 | 684 | response_part.content, dict |
655 | 685 | ): # pragma: no branch |
@@ -866,6 +896,11 @@ async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]: |
866 | 896 | vendor_part_id=event.index, |
867 | 897 | part=_map_code_execution_tool_result_block(current_block, self.provider_name), |
868 | 898 | ) |
| 899 | + elif isinstance(current_block, BetaWebFetchToolResultBlock): |
| 900 | + yield self._parts_manager.handle_part( |
| 901 | + vendor_part_id=event.index, |
| 902 | + part=_map_web_fetch_tool_result_block(current_block, self.provider_name), |
| 903 | + ) |
869 | 904 | elif isinstance(current_block, BetaMCPToolUseBlock): |
870 | 905 | call_part = _map_mcp_server_use_block(current_block, self.provider_name) |
871 | 906 | builtin_tool_calls[call_part.tool_call_id] = call_part |
@@ -972,7 +1007,14 @@ def _map_server_tool_use_block(item: BetaServerToolUseBlock, provider_name: str) |
972 | 1007 | args=cast(dict[str, Any], item.input) or None, |
973 | 1008 | tool_call_id=item.id, |
974 | 1009 | ) |
975 | | - elif item.name in ('web_fetch', 'bash_code_execution', 'text_editor_code_execution'): # pragma: no cover |
| 1010 | + elif item.name == 'web_fetch': |
| 1011 | + return BuiltinToolCallPart( |
| 1012 | + provider_name=provider_name, |
| 1013 | + tool_name=UrlContextTool.kind, |
| 1014 | + args=cast(dict[str, Any], item.input) or None, |
| 1015 | + tool_call_id=item.id, |
| 1016 | + ) |
| 1017 | + elif item.name in ('bash_code_execution', 'text_editor_code_execution'): # pragma: no cover |
976 | 1018 | raise NotImplementedError(f'Anthropic built-in tool {item.name!r} is not currently supported.') |
977 | 1019 | else: |
978 | 1020 | assert_never(item.name) |
@@ -1008,6 +1050,15 @@ def _map_code_execution_tool_result_block( |
1008 | 1050 | ) |
1009 | 1051 |
|
1010 | 1052 |
|
| 1053 | +def _map_web_fetch_tool_result_block(item: BetaWebFetchToolResultBlock, provider_name: str) -> BuiltinToolReturnPart: |
| 1054 | + return BuiltinToolReturnPart( |
| 1055 | + provider_name=provider_name, |
| 1056 | + tool_name=UrlContextTool.kind, |
| 1057 | + content=item.model_dump(mode='json', include={'content'}), |
| 1058 | + tool_call_id=item.tool_use_id, |
| 1059 | + ) |
| 1060 | + |
| 1061 | + |
1011 | 1062 | def _map_mcp_server_use_block(item: BetaMCPToolUseBlock, provider_name: str) -> BuiltinToolCallPart: |
1012 | 1063 | return BuiltinToolCallPart( |
1013 | 1064 | provider_name=provider_name, |
|
0 commit comments