1- from typing import cast
1+ from typing import Tuple , cast
22
33from anthropic import (
44 APIConnectionError ,
1313 BetaMessageParam ,
1414 BetaThinkingConfigParam ,
1515 BetaToolChoiceParam ,
16+ BetaToolUnionParam ,
1617)
1718from tenacity import retry , retry_if_exception , stop_after_attempt , wait_exponential
1819from typing_extensions import override
2324 RETRYABLE_HTTP_STATUS_CODES ,
2425 wait_for_retry_after_header ,
2526)
26- from askui .models .shared .agent_message_param import MessageParam
27+ from askui .models .shared .agent_message_param import (
28+ MessageParam ,
29+ ThinkingConfigParam ,
30+ ToolChoiceParam ,
31+ )
2732from askui .models .shared .messages_api import MessagesApi
2833from askui .models .shared .prompts import SystemPrompt
2934from askui .models .shared .tools import ToolCollection
@@ -36,6 +41,47 @@ def _is_retryable_error(exception: BaseException) -> bool:
3641 return isinstance (exception , (APIConnectionError , APITimeoutError , APIError ))
3742
3843
44+ def _parse_to_anthropic_types (
45+ tools : ToolCollection | None ,
46+ betas : list [str ] | None = None ,
47+ system : SystemPrompt | None = None ,
48+ thinking : ThinkingConfigParam | None = None ,
49+ tool_choice : ToolChoiceParam | None = None ,
50+ temperature : float | None = None ,
51+ ) -> Tuple [
52+ list [BetaToolUnionParam ] | Omit ,
53+ list [AnthropicBetaParam ] | Omit ,
54+ str | Omit ,
55+ BetaThinkingConfigParam | Omit ,
56+ BetaToolChoiceParam | Omit ,
57+ float | Omit ,
58+ ]:
59+ """Convert provider-agnostic types to Anthropic-specific types.
60+
61+ This function bridges the gap between the generic MessagesApi interface
62+ and Anthropic's specific type requirements. The input dicts should match
63+ Anthropic's expected structure (see Anthropic SDK documentation).
64+ """
65+ _tools = (
66+ cast ("list[BetaToolUnionParam]" , tools .to_params ())
67+ if tools is not None
68+ else omit
69+ )
70+ _betas = cast ("list[AnthropicBetaParam]" , betas ) or omit
71+ _system : str | Omit = omit if system is None else str (system )
72+ # Cast dicts to Anthropic's TypedDict types
73+ # Runtime validation happens in Anthropic SDK
74+ _thinking = (
75+ cast ("BetaThinkingConfigParam" , thinking ) if thinking is not None else omit
76+ )
77+ _tool_choice = (
78+ cast ("BetaToolChoiceParam" , tool_choice ) if tool_choice is not None else omit
79+ )
80+ _temperature = temperature or omit
81+
82+ return (_tools , _betas , _system , _thinking , _tool_choice , _temperature )
83+
84+
3985class AnthropicMessagesApi (MessagesApi ):
4086 def __init__ (
4187 self ,
@@ -45,7 +91,6 @@ def __init__(
4591 self ._client = client
4692 self ._locator_serializer = locator_serializer
4793
48- @override
4994 @retry (
5095 stop = stop_after_attempt (4 ), # 3 retries
5196 wait = wait_for_retry_after_header (
@@ -59,30 +104,35 @@ def create_message(
59104 self ,
60105 messages : list [MessageParam ],
61106 model_id : str ,
62- tools : ToolCollection | Omit = omit ,
63- max_tokens : int | Omit = omit ,
64- betas : list [AnthropicBetaParam ] | Omit = omit ,
107+ tools : ToolCollection | None = None ,
108+ max_tokens : int | None = None ,
109+ betas : list [str ] | None = None ,
65110 system : SystemPrompt | None = None ,
66- thinking : BetaThinkingConfigParam | Omit = omit ,
67- tool_choice : BetaToolChoiceParam | Omit = omit ,
68- temperature : float | Omit = omit ,
111+ thinking : ThinkingConfigParam | None = None ,
112+ tool_choice : ToolChoiceParam | None = None ,
113+ temperature : float | None = None ,
69114 ) -> MessageParam :
70115 _messages = [
71116 cast ("BetaMessageParam" , message .model_dump (exclude = {"stop_reason" }))
72117 for message in messages
73118 ]
74- _system : str | Omit = omit if system is None else str (system )
119+
120+ _tools , _betas , _system , _thinking , _tool_choice , _temperature = (
121+ _parse_to_anthropic_types (
122+ tools , betas , system , thinking , tool_choice , temperature
123+ )
124+ )
75125
76126 response = self ._client .beta .messages .create ( # type: ignore[misc]
77127 messages = _messages ,
78128 max_tokens = max_tokens or 8192 ,
79129 model = model_id ,
80- tools = tools . to_params () if not isinstance ( tools , Omit ) else omit ,
81- betas = betas ,
130+ tools = _tools ,
131+ betas = _betas ,
82132 system = _system ,
83- thinking = thinking ,
84- tool_choice = tool_choice ,
85- temperature = temperature ,
133+ thinking = _thinking ,
134+ tool_choice = _tool_choice ,
135+ temperature = _temperature ,
86136 timeout = 300.0 ,
87137 )
88138 return MessageParam .model_validate (response .model_dump ())
0 commit comments