ó
    °"³j °  ã                  ó|  • % S SK Jr  S SKrS SKrS SKJrJrJrJr  S SK	J
r
Jr  S SKJr  S SKJrJr  S SKJr  S SKJrJrJrJrJrJrJr  S S	KJr  S S
KJr  S SK J!r!  S SK"J#r#J$r$J%r%J&r&J'r'J(r(  S SK)J*r*  S SK+J,r,J-r-  S SK.J/r/J0r0  S SK1J2r2  SSK3J4r4  \(       a,  S SK5J6r6  S SK7J8r8  S SK9J:r:J;r;J<r<  S SK=J>r>J?r?J@r@  S SKAJBrB  S SKCJDrD  SrE SrFSrGSrHSrISrJSrKS rLS!\MS"'   \-\   " \5      rN\-\   " \\," S#S$9S%9rOS&rPS'rQ\" S(S)9 " S* S+5      5       rR\" S,SS-9rSS.\MS/'    S]S0 jrT\" S1SS-9rUS2\MS3'    \" S(S49 " S5 S65      5       rV\W\X\V4   rYS7\MS8'    S^S9 jrZS:r[S_S; jr\S`S< jr]SaS= jr^SbS> jr_ScS? jr`        SdS@ jraSeSA jrbSfSgSB jjrcShSC jrd        SiSD jreS(SE.     SjSF jjrfSkSG jrgSlSH jrh\SmSI j5       riSnSJ jrjSoSK jrkSpSL jrl Sf       SqSM jjrmSrSN jrn " SO SP\5      roS(SQ.SsSR jjrpStSS jrq\SuST j5       rr\SSU.       SvSV jj5       rsSwSW jrt Sf     SxSX jjruSySY jrvSzSZ jrw\" S(S)9 " S[ S\5      5       rxg){é    )ÚannotationsN)ÚCallableÚ	GeneratorÚMappingÚSequence)ÚAbstractContextManagerÚcontextmanager)Ú
ContextVar)Ú	dataclassÚreplace)Úcache)ÚTYPE_CHECKINGÚAnyÚClassVarÚLiteralÚProtocolÚ	TypeAliasÚcast)Úurlparse)Úcontext)Úget_baggage)ÚINVALID_SPANÚSpanÚSpanKindÚStatusÚ
StatusCodeÚget_current_span)ÚAttributeValue)Ú
ConfigDictÚTypeAdapter)ÚPydanticSerializationErrorÚto_json)Úget_traceparenté   )Úbest_effort_price)ÚPriceCalculation)ÚSelf)ÚModelMessageÚModelRequestÚModelResponse)ÚAbstractModelÚModelRequestContextÚModelRequestParameters)ÚInstrumentationSettings)ÚModelSettingsé   úgen_ai.agent.namezgen_ai.agent.call.idzgen_ai.conversation.idzgen_ai.systemzgen_ai.request.modelzgen_ai.provider.name)Ú
max_tokensÚtop_pÚseedÚtemperatureÚpresence_penaltyÚfrequency_penaltyzjtuple[Literal['max_tokens', 'top_p', 'seed', 'temperature', 'presence_penalty', 'frequency_penalty'], ...]ÚMODEL_SETTING_ATTRIBUTESÚbase64)Úser_json_bytes)Úconfig)r$   é   é   é@   é   i   i   i @  i   i   i   i  @ i   i   )g{®Gáz„?g{®Gáz”?g{®Gáz¤?g{®Gáz´?g{®GázÄ?g{®GázÔ?g{®Gázä?g{®Gázô?g{®Gáz@g{®Gáz@g{®Gáz$@g{®Gáz4@g{®GázD@g{®GázT@T)Úfrozenc                  ó.   • \ rS rSr% SrS\S'   S\S'   Srg)	ÚContentPolicyéP   a  One span's `include_content`, tagged with the span it was set for.

The tag is what makes the variable safe to read. Restoring it is a plain `set` rather than a
`reset` (an interrupted streamed run finalizes the context manager in a different `Context`,
where `reset` raises), and a `set` lands only in the `Context` that runs it, so the `Context`
that opened the request can be left holding a finished request's value. Naming the span means a
reader can only honour a policy set for the span in front of it, and anything else fails closed.
ÚintÚspan_idÚboolÚinclude_content© N©Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__annotations__Ú__static_attributes__rH   ó    ÚY/home/mande/repo/quber/.venv/lib/python3.13/site-packages/pydantic_ai/_instrumentation.pyrB   rB   P   s   ‡ ñð ƒLØÖrQ   rB   rG   )Údefaultz ContextVar[ContentPolicy | None]Úinclude_content_ctxc                ó´   • [         R                  5       nUSL=(       a:    UR                  U R                  5       R                  :H  =(       a    UR                  $ )a  Whether `span` was opened with content capture, defaulting to `False` when nothing says so.

Fails closed on every answer but "this span's own request wanted content": no request open, or a
policy belonging to a different span, both mean nothing vouches for exporting content here.
N)rT   ÚgetrE   Úget_span_contextrG   )ÚspanÚpolicys     rR   Úspan_include_contentrZ   m   sF   € ô !×$Ñ$Ó&€FØ˜Ð×n &§.¡.°D×4IÑ4IÓ4K×4SÑ4SÑ"S×nÐX^×XnÑXnÐnrQ   Útime_to_first_chunkzContextVar[float | None]Útime_to_first_chunk_ctx)Úslotsc                  ó<   • \ rS rSr% SrS\S'    S\S'    S\S'   S	rg
)ÚCachedMessageJsonéƒ   zNA `MessageJsonCache` entry: one input message's serialized OTel JSON fragment.r(   ÚmessageÚobjectÚpartsÚbytesÚfragmentrH   NrI   rH   rQ   rR   r_   r_   ƒ   s'   ‡ áXàÓðFð ƒMðð ƒOÚ@rQ   r_   r   ÚMessageJsonCachec                 ó¦   • 0 n [        [        5      nUb  X[        '   [        [        5      nUb  X [        '   [        [        5      nUb  X0[        '   U $ )z]Read agent name, run ID, and conversation ID from OTel baggage and return as span attributes.)r   ÚAGENT_NAME_BAGGAGE_KEYÚRUN_ID_BAGGAGE_KEYÚCONVERSATION_ID_BAGGAGE_KEY)ÚattrsÚ
agent_nameÚrun_idÚconversation_ids       rR   Ú get_agent_run_baggage_attributesro   ¤   sZ   € à€EÜÔ3Ó4€JØÑØ(2Ô$Ñ%ÜÔ+Ó,€FØÑØ$*Ô Ñ!Ü!Ô"=Ó>€OØÑ"Ø-<Ô)Ñ*Ø€LrQ   z<circular reference>c                ó°   • UR                   (       a  U $  [        U [        5       5      $ ! [         a"  nS[	        U5      R
                   3s SnA$ SnAff = f)al  Strip binary data out of a value that's about to be serialized into a span attribute.

The attributes that carry whatever a tool or output function produced serialize arbitrary
values, so they can't honor `include_binary_content` the way `_convert_binary_to_otel_part`
does for message content: `BinaryContent`'s own serialization is a public contract shared with
message history, and making it depend on instrumentation would change how it dumps everywhere.
The value is redacted up front instead, keeping the media type and the rest of the file
metadata, and dropping only the data. That retained set is `BinaryContent`'s own and is wider
than the `mime_type` `_convert_binary_to_otel_part` keeps, because this replaces a value the
type itself serialized rather than building a spec-shaped message part.

Containers and `ToolReturn` are walked, matching the depth at which binary content is honored
elsewhere (the sequence in a `UserPromptPart`'s content). A `BinaryContent` nested inside a
user's own model is left alone: rebuilding that model to redact one field would change how
everything else in the attribute is serialized.
z!Unable to redact binary content: N)Úinclude_binary_contentÚ_redact_binary_contentÚsetÚ	ExceptionÚtyperJ   )ÚvalueÚsettingsÚes      rR   Úredact_binary_contentry   ¶   sS   € ð" ×&×&ØˆðFÜ% e¬S«UÓ3Ð3øÜó Fð
 3´4¸³7×3CÑ3CÐ2DÐEÕEûðFús   •) ©
A³AÁ
AÁAc           	     óf  • SSK Jn  SSKJnJn  [        U 5      n[        XXB[        [        [        45      (       d  U $ XQ;   a  [        $ UR                  U5         [        X5      (       aJ  U R                  [        U R                  U5      U R                  U R                   S.UR#                  U5        $ [        X5      (       ai  [        U R$                  U5      [        U R&                  U5      [        U R(                  U5      U R*                  U R                  S.UR#                  U5        $ [        X5      (       aS  [        U R,                  U5      [        U R.                  U5      [        U R(                  U5      S.UR#                  U5        $ [        U [        5      (       a@  U R1                  5        VVs0 s H  u  pgU[        Xq5      _M     snnUR#                  U5        $ U  Vs/ s H  n[        Xq5      PM     snUR#                  U5        $ s  snnf s  snf ! UR#                  U5        f = f)Nr   )ÚDeferredToolRequests)ÚBinaryContentÚ
ToolReturn)Ú
media_typeÚvendor_metadataÚkindÚ
identifier)Úreturn_valueÚcontentÚmetadataÚtoolsr€   )ÚcallsÚ	approvalsr„   )Úpydantic_ai._deferredr{   Úpydantic_ai.messagesr|   r}   ÚidÚ
isinstancer   ÚlistÚtupleÚCIRCULAR_REFERENCE_PLACEHOLDERÚaddr~   rr   r   r€   r�   Údiscardr‚   rƒ   r„   r…   r†   r‡   Úitems)rv   Úactiver{   r|   r}   ÚidentityÚkeyÚitems           rR   rr   rr   Ó   sÉ  € Ý:ß>ä�%‹y€HÜ�e¨ZÌwÔX\Ô^cÐd×eÑeØˆØÓÜ-Ð-ð
 ‡J�JˆxÔð!!Ü�e×+Ñ+à#×.Ñ.ä#9¸%×:OÑ:OÐQWÓ#XØŸ
™
Ø#×.Ñ.ñð> 	�‰�xÕ ô1 �e×(Ñ(ä 6°u×7IÑ7IÈ6Ó RÜ1°%·-±-ÀÓHÜ2°5·>±>À6ÓJàŸ™ØŸ
™
ñð. 	�‰�xÕ ô �e×2Ñ2ô 0°·±¸VÓDÜ3°E·O±OÀVÓLÜ2°5·>±>À6ÓJñð 	�‰�xÕ ô �eœW×%Ñ%ð "'§¡¤ôâ!.‘I�Cð Ô+¨DÓ9Ò9Ù!.òð 	�‰�xÕ ñ BGÓGÂ¸Ô& tÖ4ÁÑGà�‰�xÕ ùóùò Høà�‰�xÕ úsE   ÁAH Â4A'H Ä-AH Æ(H Æ8HÇH Ç%H Ç)HÇ>H ÈH ÈH0c                óê   •   [         R                  U SS9$ ! [         a    [        R                  U SS9s $ f = f! [         a-     [        U 5      s $ ! [         a  nSU 3s S nAs $ S nAff = ff = f)NÚjson©ÚmodezUnable to serialize: )ÚANY_ADAPTERÚdump_pythonÚUnicodeDecodeErrorÚ_BASE64_ANY_ADAPTERrt   Ústr)rv   rx   s     rR   Úserialize_anyrŸ     s„   € ð	/ð	GÜ×*Ñ*¨5°vÐ*Ð>Ð>øÜ!ó 	GÜ&×2Ñ2°5¸vÐ2ÐFÒFð	Gûäó /ð	/Ü�u“:ÒøÜó 	/Ø*¨1¨#Ð.×.ûð	/úð/úsI   ƒ —8µ; ·8¸; »
A2Á
AÁA2Á
A.ÁA)Á!A.Á"A2Á)A.Á.A2c                ó€   •  [        U 5      $ ! [         a&    [        R                  " U SS9R	                  5       s $ f = f)aU  Serialize `value` to compact JSON bytes, tolerating lone surrogates.

`to_json` raises on unpaired surrogates (e.g. text decoded with `errors='surrogateescape'`),
which would crash an otherwise-successful run from within instrumentation. The stdlib fallback
escapes them, matching the lenient behavior callers had before adopting `to_json`.
)Ú,Ú:)Ú
separators)r"   r!   r—   ÚdumpsÚencode)rv   s    rR   Úsafe_to_jsonr¦     s=   € ðAÜ�u‹~ÐøÜ%ó AÜ�zŠz˜%¨JÑ7×>Ñ>Ó@Ò@ðAús   ‚
 �-=¼=c                ó>   • [        U R                  U/5      5      SS $ )u|  Serialize one message to its OTel JSON fragment: comma-joined objects without enclosing brackets.

A single `ModelMessage` can map to multiple OTel `ChatMessage`s (a `ModelRequest` splits into
system/user messages) or to none (an empty request), so the fragment is the whole serialized
array with the outer `[` and `]` stripped â€” fragments then concatenate into a single array.
r$   éÿÿÿÿ)r¦   Úmessages_to_otel_messages)rw   ra   s     rR   Úmessage_json_fragmentrª     s#   € ô ˜×:Ñ:¸G¸9ÓEÓFÀqÈÐLÐLrQ   c                óÂ   • U HY  nUR                   " [        U5      5      nUc  M#  UR                  UR                  L d  M>  UR                  [	        X5      :w  d  MY    g   g)uï  Detect whether in-place mutation made any cached message fragment stale.

Re-serializes each message that still has a valid cache entry (same `parts` list) and compares
bytes â€” an O(history) pass meant to run once per run, at the end. Entries whose `parts` token no
longer matches are skipped: reassigning `.parts` is the supported mutation style and the next
serialization would have refreshed them, so they can't have produced a stale span.

Detection is deliberately best-effort, covering messages still present at the end of the run: a
message that was mutated in place and *then* dropped or rebuilt by a history processor may have
produced a stale span without a warning. Closing that gap would require either re-checking
cached fragments on every request (the O(history-squared) cost this cache exists to remove) or
re-serializing entries as they're evicted (which doubles the serialization cost for processors
that rebuild history each request â€” the workload the cache can't help to begin with).
TF)rV   rŠ   rc   re   rª   )rw   Úmessagesr   ra   Úentrys        rR   Úhas_stale_message_jsonr®   )  sP   € ó" ˆØ—	’	œ"˜W›+Ó&ˆàÓØ—‘˜wŸ}™}Ô,Ø—‘Ô"7¸Ó"JÕJáñ ð rQ   c                ó°   • 0 nU (       a;   [        U 5      nUR                  UR                  pCU(       a  X1S'   U(       a  XAS'   U$ U$ ! [         a     U$ f = f)a¨  Map a model's `base_url` to the OTel `server.*` attributes, omitting what it doesn't carry.

`base_url` is an overridable property returning an arbitrary string, and `urlparse` defers
authority validation to `hostname`/`port`, so a non-numeric port parses fine and only raises
when the port is read. Attributes are best-effort telemetry, so an uninterpretable authority
yields no attributes rather than failing the request.
zserver.addresszserver.port)r   ÚhostnameÚportÚ
ValueError)Úbase_urlÚ
attributesÚparsedr°   r±   s        rR   Úserver_attributesr¶   E  sj   € ð -/€JÞð		1Ü˜hÓ'ˆFØ#Ÿ_™_¨f¯k©k�dö Ø/7Ð+Ñ,ÞØ,0˜=Ñ)àÐˆ:Ðøô ó 	Øð Ðð	ús   ‹"A Á
AÁAc                ó4   • [         U [        U 0[        U5      E$ )zUBuild the provider and server attributes shared by classic and realtime `chat` spans.)ÚGEN_AI_PROVIDER_NAME_ATTRIBUTEÚGEN_AI_SYSTEM_ATTRIBUTEr¶   )Úsystemr³   s     rR   Úprovider_attributesr»   ]  s'   € ô 	'¨Ü ðô ˜HÓ
%ðð rQ   c                ój   • 0 [        U R                  U R                  5      E[        U R                  0E$ ©N)r»   rº   r³   ÚGEN_AI_REQUEST_MODEL_ATTRIBUTEÚ
model_name)Úmodels    rR   Úmodel_attributesrÁ   f  s3   € ðÜ
˜eŸl™l¨E¯N©NÓ
;ðä&¨×(8Ñ(8ñð rQ   c                óX   • SS0nU b  X[         '   X[        '   Ub  X[        '   Ub  X#S'   U$ )zIBuild the dimensions shared by classic and realtime per-response metrics.úgen_ai.operation.nameÚchatúgen_ai.response.model)r¸   r¹   r¾   )Úprovider_nameÚrequest_modelÚresponse_modelr´   s       rR   Úmodel_metric_attributesrÉ   m  sK   € ð .EÀfÐ,M€JØÑ Ø5BÔ1Ñ2Ø.;Ô*Ñ+ØÑ Ø5BÔ1Ñ2ØÑ!Ø.<Ð*Ñ+ØÐrQ   ©rG   c               ó|   • [        U 5      nU(       d  [        U5      nUc  0 $ S[        U5      R                  5       0$ )NÚmodel_request_parameters)Ú#_serialize_model_request_parametersÚ _redact_model_request_parametersr¦   Údecode)rÌ   rG   Ú
serializeds      rR   Ú#model_request_parameters_attributesrÑ   ~  s@   € ô 5Ð5MÓN€JÞÜ5°jÓAˆ
ØÑØˆIØ&¬°ZÓ(@×(GÑ(GÓ(IÐJÐJrQ   c                ó  • [        U [        5      (       d  g[        SU 5      nUR                  S5      n[        U[        5      (       a%  [        SU5       H  nUR                  SS5        M     UR                  S5      b  SUS'   U$ )aP  Drop the prompt text the user wrote, or `None` when the shape cannot be redacted.

Two fields here are that text: the instructions, whose dynamic parts can be built from deps, and
the prompted-output template. Instruction parts keep their origin and ids, so what the parts are
and how they cache stays visible. Tool and output *schemas* stay too -- they are the request's
structure rather than message content, and `include_model_request_parameters=False` drops the
whole attribute for anyone who wants them gone as well.

`_serialize_model_request_parameters` falls back to inferring a shape, which for a value it cannot
walk -- a tool whose `metadata` holds an arbitrary object, say -- is the request's string
representation, instructions and all. There is nothing to redact in a string, so that is reported
as unredactable rather than exported.
Núdict[str, Any]Úinstruction_partsúlist[dict[str, Any]]rƒ   Úprompted_output_template)r‹   Údictr   rV   rŒ   Úpop)Úserialized_parametersÚ
parametersrc   Úparts       rR   rÎ   rÎ   ‰  s€   € ô Ð+¬T×2Ñ2ØÜÐ&Ð(=Ó>€JØ�N‰NÐ.Ó/€EÜ�%œ×ÑäÐ/°Ö7ˆDØ�H‰H�Y Ö%ñ 8à‡~�~Ð0Ó1Ñ=Ø15ˆ
Ð-Ñ.ØÐrQ   c                ój   •  [        5       R                  U SS9$ ! [         a    [        U 5      s $ f = f)aô  Serialize the parameters through their own schema, falling back to inference.

`serialize_any` infers a shape from the value, which reads a dataclass as its fields and so
loses whatever its class meant. `InstructionPart.id` is exactly that case: its source is a
class rather than a tagged field, so inference renders a toolset and a capability sharing an
`id` identically and drops the agent's source to `{}`. The declared schema renders the id as
the same flat key it serializes to everywhere else.
r—   r˜   )Ú!_model_request_parameters_adapterr›   rt   rŸ   )rÌ   s    rR   rÍ   rÍ   ¤  s=   € ð7Ü0Ó2×>Ñ>Ð?WÐ^dÐ>ÐeÐeøÜó 7äÐ5Ó6Ò6ð7ús   ‚ š2±2c                 ó$   • SSK Jn   [        U 5      $ )Nr   ©r-   )Úpydantic_ai.modelsr-   r    rß   s    rR   rÝ   rÝ   ´  s   € å9äÐ-Ó.Ð.rQ   c                óž   • 0 nU (       aC  [          H9  n[        U R                  U5      =n[        [        -  5      (       d  M2  X1SU 3'   M;     U$ )zeMap the OTel-spec model settings (`max_tokens`, `temperature`, ...) to `gen_ai.request.*` attributes.zgen_ai.request.)r8   r‹   rV   ÚfloatrD   )Úmodel_settingsr´   r”   rv   s       rR   Úmodel_settings_attributesrä   »  sL   € à,.€JÞß+ˆCÜ >×#5Ñ#5°cÓ#:Ð:˜%¼EÄC¹K×HÓHØ6;˜_¨S¨EÐ2Ó3ñ ,ð ÐrQ   c                ó¶  • SSK Jn  SSKJn  UR                  nU(       d  gU R
                   H©  n[        XS5      (       d  M  UR                  UR                  5      =n(       d  M9  UR                  (       d  ML  0 nUR                  R                  S5      =n(       a  X‡S'   UR                  R                  S5      =n	(       a  X—S'   U(       d  M£  Xul
        M«     g)a  Copy OTel-relevant metadata from tool definitions onto matching tool call parts.

This allows tool definition metadata (e.g. code language hints set by the code-mode toolset)
to flow through to OTel events on both the model request span and the agent run span.
r   )Ú_otel_messages)ÚBaseToolCallPartNÚcode_arg_nameÚcode_arg_language)Úpydantic_airæ   r‰   rç   Ú	tool_defsrc   r‹   rV   Ú	tool_namer„   Úotel_metadata)
ÚresponserÚ   ræ   rç   rë   rÛ   Útool_defrí   rè   ré   s
             rR   Ú annotate_tool_call_otel_metadatarð   Å  s²   € õ +Ý5à×$Ñ$€IÞØØ—”ˆÜ�d×-Ó-¸y¿}¹}ÈTÏ^É^Ó?\Ð3\°8×3\Ø× × Ñ ØIK�Ø$,×$5Ñ$5×$9Ñ$9¸/Ó$JÐJ�=ÕJØ5B /Ñ2Ø(0×(9Ñ(9×(=Ñ(=Ð>QÓ(RÐRÐ$ÕRØ9JÐ"5Ñ6ß �=Ø)6Ö&ò rQ   c                ó˜  • [         R                  " U R                  =(       d    / U R                  =(       d    / 5      n/ nU H„  nU R	                  UR
                  5      S:X  a  M$  SUR
                  S.nUR                  (       a  UR                  US'   UR                  (       a  UR                  US'   UR                  U5        M†     U$ )zÝBuild OTel-compliant tool definitions from model request parameters.

Extracts tool metadata from function_tools and output_tools into a list of
tool definition dicts following the OTel GenAI semantic conventions format.
ÚwithheldÚfunction)ru   ÚnameÚdescriptionrÚ   )	Ú	itertoolsÚchainÚfunction_toolsÚoutput_toolsÚvisibility_ofrô   rõ   Úparameters_json_schemaÚappend)rÌ   Ú	all_toolsÚtool_definitionsÚtoolrï   s        rR   Úbuild_tool_definitionsr   Ý  s²   € ô —’Ø ×/Ñ/×5°2Ø ×-Ñ-×3°ó€Ið
 .0ÐÛˆØ#×1Ñ1°$·)±)Ó<À
ÓJñ
 Ø,6ÀÇ	Á	Ñ#JˆØ××Ø&*×&6Ñ&6ˆH�]Ñ#Ø×&×&Ø%)×%@Ñ%@ˆH�\Ñ"Ø×Ñ Ö)ñ ð ÐrQ   c                óô   • 0 U R                   R                  5       EnUb  XS'   Ub  [        UR                  5      US'   U R                  b  U R                  US'   U R
                  b  U R
                  /US'   U$ )a�  Build the `gen_ai.response.*`, usage, and cost span attributes for a completed response.

Shared between the classic model-request span (`open_model_request_span`) and the realtime
session's per-turn `chat` span so the two paths report the same shape and can't drift.
`response_model` is set only when known (always the case for a classic request; a realtime
session may not know its model name).
rÅ   zoperation.costzgen_ai.response.idzgen_ai.response.finish_reasons)ÚusageÚopentelemetry_attributesrâ   Útotal_priceÚprovider_response_idÚfinish_reason)rî   rÈ   Úprice_calculationr´   s       rR   Úresponse_attributesr  ú  s‹   € ð -Z¨x¯~©~×/VÑ/VÓ/XÐ,Y€JØÑ!Ø.<Ð*Ñ+ØÑ$Ü',Ð->×-JÑ-JÓ'Kˆ
Ð#Ñ$Ø×$Ñ$Ñ0Ø+3×+HÑ+Hˆ
Ð'Ñ(Ø×ÑÑ)Ø8@×8NÑ8NÐ7Oˆ
Ð3Ñ4ØÐrQ   c                ó€   • [        U R                  U R                  U R                  U R                  U R
                  S9$ )zYPrice a response, degrading any pricing-data failure to `None` (see `best_effort_price`).)r¿   Úprovider_api_urlrÆ   Úgenai_request_timestamp)r%   r  r¿   Úprovider_urlrÆ   Ú	timestamp)rî   s    rR   Úresponse_price_calculationr    s:   € äØ�‰Ø×&Ñ&Ø!×.Ñ.Ø×,Ñ,Ø (× 2Ñ 2ñð rQ   c                  ó&   • \ rS rSrSrSSS jjrSrg)Ú_FinishModelRequestSpani  z™The `finish` callback yielded by `open_model_request_span`.

`time_to_first_chunk` is the streaming-only TTFT in seconds; non-streaming
callers omit it.
Nc                ó   • g r½   rH   )Úselfrî   r[   s      rR   Ú__call__Ú _FinishModelRequestSpan.__call__$  s   € ÐcfrQ   rH   r½   ©rî   r*   r[   zfloat | NoneÚreturnÚNone)rJ   rK   rL   rM   rN   r  rP   rH   rQ   rR   r  r    s   † ñ÷ gÑfrQ   r  ©Úescapedc               ó  • U R                  5       (       d  gU(       a  U R                  XS9  g[        U5      nUR                  S:w  a  UR                   SUR                   3OUR                  nU R                  SU[        U5      S.S9  g)a�  Record `error` on `span` as an `exception` event.

With content capture enabled this is the OTel SDK's own `Span.record_exception`. Without it,
only the exception type is kept: the message and stack trace of an exception raised around
a tool, a model request or an agent run can quote content the setting is meant to withhold --
a tool retry or failure carries the text the model sees, an exception chained from one repeats
that text in its stack trace, a provider's error response can echo the request, and validation
errors and user exceptions may echo the rejected arguments. The type and `escaped` formatting
match what `Span.record_exception` would have produced.
Nr  ÚbuiltinsÚ.Ú	exception)zexception.typezexception.escaped)r´   )Úis_recordingÚrecord_exceptionru   rK   rL   Ú	add_eventrž   )rX   ÚerrorrG   r  Ú
error_typeÚ	type_names         rR   r  r  '  s�   € ð ×Ñ×ÑØÞØ×Ñ˜eÐÑ5ØÜ�e“€Jð × Ñ  JÓ.ð × Ñ Ð
!  :×#:Ñ#:Ð";Ñ<à×$Ñ$ð ð 	‡N�N�;¸iÔ^aÐbiÓ^jÑ+k€NÒlrQ   c               óÀ   • U R                  5       (       d  gU R                  [        [        R                  U(       a  [        U5      R                   SU 3OSS95        g)zúSet `span`'s status to ERROR, describing it the way `use_span` would have.

The SDK's description is `f'{type(exc).__name__}: {exc}'`, which repeats the message the
exception event carries, so it is withheld alongside it when content capture is off.
Nz: )rõ   )r  Ú
set_statusr   r   ÚERRORru   rJ   )rX   r!  rG   s      rR   Úset_error_statusr'  D  sN   € ð ×Ñ×ÑØØ‡O�OÜŒz×ÑÖSb´°U³×0DÑ0DÐ/EÀRÈÀwÑ-OÐhlÑmõrQ   c             #  óf   #   •  Sv •  g! [          a  n[        XUSS9  [        XUS9  e SnAff = f7f)aø  Record exceptions leaving `span`'s scope the way `use_span` would have.

For spans opened with `record_exception=False` and `set_status_on_exception=False`, which hands
both jobs to the caller. `use_span` recorded the exception unescaped and described the ERROR
status with it; both repeat the message, so both follow `include_content`. Enter this around
the span's whole scope -- the scope `use_span` covered -- not just the call that may fail, so
that failures while finalizing the span still mark it.
NF)rG   r  rÊ   )rt   r  r'  )rX   rG   r!  s      rR   Úrecord_uncaught_errorsr)  Q  s5   é € ðÜøÜó Ü˜°oÈuÒUÜ˜°oÒFØûðüs   ‚1„	 ˆ1‰
.“)©.®1©Úmessage_json_cachec             #  ó˜  ^ ^^
^^^^^#   • UR                   nUR                  UR                  UR                  5      u  nm[	        XTS9mSmT SUR
                   3nST0[        U5      E[        5       Em
0 nT R                  (       a*  T
R                  [        TT R                  S95        SS0US'   [        SUS	.5      R                  5       T
S
'   [        T5      nU(       a  [        U5      R                  5       T
S'   T
R                  [!        U5      5        Sm["        R%                  5       n T R&                  R)                  UT
[*        R,                  SSS9 m[/        TT R                  S9   ["        R1                  [3        TR5                  5       R6                  T R                  5      5        SSU
UUUUUU U4S jjjn	U	T4v •  SSS5        SSS5        ["        R1                  U5        T(       a  T" 5         gg! , (       d  f       N;= f! , (       d  f       ND= f! ["        R1                  U5        T(       a  T" 5         f f = f7f)a   Open a `chat <model>` CLIENT span; yield `(finish, prepared_request_context)`.

Shared between `Instrumentation.wrap_model_request` (agent flow) and
`InstrumentedModel.request`/`request_stream` (standalone / `direct.model_request*`).
Calls `model.prepare_request(...)` internally and yields a request context with the prepared
settings/parameters so callers don't have to re-prepare. `finish(response)` annotates the
response with OTel tool-call metadata and records outcome attributes. Token/cost metrics are
recorded *after* the span closes so backends that aggregate from span attributes don't
double-count.

`message_json_cache` is a per-run cache reused across requests so the growing input history
isn't re-serialized in full each time; the agent flow passes one, one-off requests pass `None`.
)rã   rÌ   rÄ   Ú rÃ   rÊ   ru   rb   rÌ   )ru   Ú
propertieszlogfire.json_schemazgen_ai.tool.definitionsNF)r´   r€   r  Úset_status_on_exceptionc                óä  >^ ^^^^^• [        T T5        TR                  [        TS0 5      5        T[           m[	        [
        T[           5      mT R                  =(       d    TmS mSUUU UUUU4S jjnUm[        T 5      mTR                  5       (       d  g TR                  TR                  T TTT	S9  [        T TT5      nTb  TUS'   TR                  U5        TR                  T
 ST 35        g )Nr´   c                 óH   >• [        TTT5      n TR                  TTU T5        g r½   )rÉ   Úrecord_metrics)Úmetric_attributesr  rÇ   rî   rÈ   rw   rº   r[   s    €€€€€€€rR   Ú_record_metricsÚ@open_model_request_span.<locals>.finish.<locals>._record_metrics¸  s*   ø€ Ü(?ÀÈÐWeÓ(fÐ%Ø×+Ñ+¨HÐ6GÐIZÐ\oÕprQ   r*  z+gen_ai.client.operation.time_to_first_chunkr-  )r  r  )rð   ÚupdateÚgetattrr¾   r   rž   r¹   r¿   r  r  Úhandle_messagesr¬   r  Úset_attributesÚupdate_name)rî   r[   r4  Úattributes_to_setr  rÇ   rÈ   rº   r´   r+  Ú	operationÚprepared_parametersÚprepared_request_contextr2  rw   rX   s   ``  @@@@€€€€€€€€rR   ÚfinishÚ'open_model_request_span.<locals>.finish«  s  þ€ ô 1°Ð;NÔOð ×!Ñ!¤'¨$°¸bÓ"AÔBØ *Ô+IÑ J�Üœc :Ô.EÑ#FÓG�à!)×!4Ñ!4×!E¸�Ø=AÐ!÷qõ qð "1�ô %?¸xÓ$HÐ!à×(Ñ(×*Ñ*Øà×(Ñ(Ø,×5Ñ5ØØØ'Ø'9ð )ñ ô %8¸À.ÐRcÓ$dÐ!Ø&Ñ2ØWjÐ%Ð&SÑTØ×#Ñ#Ð$5Ô6Ø× Ñ  I ;¨a°¨Ð!?Õ@rQ   r½   r  )rÀ   Úprepare_requestrã   rÌ   r   r¿   rÁ   ro   Ú include_model_request_parametersr6  rÑ   rG   r"   rÏ   r   r¦   rä   rT   rV   ÚtracerÚstart_as_current_spanr   ÚCLIENTr)  rs   rB   rW   rE   )rw   Úrequest_contextr+  rÀ   Úprepared_settingsÚ	span_nameÚjson_schema_propertiesrþ   Úprevious_include_contentr?  r´   r<  r=  r>  r2  rX   s   ` `       @@@@@@rR   Úopen_model_request_spanrK  c  s<  ÿé € ð. ×!Ñ!€EØ-2×-BÑ-BØ×&Ñ&¨×(PÑ(Pó.Ñ*ÐÐ*ô  'ØÐTgñ Ðð €IØ�+˜Q˜u×/Ñ/Ð0Ð1€Ià ð-ä
˜5Ó
!ð-ô +Ó
,ð-€Jð
 9;ÐØ×0×0Ø×ÑÜ/Ð0CÐU]×UmÑUmÑnô	
ð ?EÀhÐ=OÐÐ9Ñ:Ü(/¸ÐQgÑ0hÓ(i×(pÑ(pÓ(r€JÐ$Ñ%ä-Ð.AÓBÐÞÜ0<Ð=MÓ0N×0UÑ0UÓ0Wˆ
Ð,Ñ-à×ÑÔ/Ð0AÓBÔCà04€NÜ2×6Ñ6Ó8Ðð?à�O‰O×1Ñ1ØØ%Ü—_‘_Ø!&Ø(-ð 2ñ ð Ü" 4¸×9QÑ9QÓRô  ×#Ñ#¤M°$×2GÑ2GÓ2I×2QÑ2QÐS[×SkÑSkÓ$lÔm÷&A÷ &Að &AðP Ð2Ð2Ò2÷e S÷ôv 	×ÑÐ 8Ô9ÞÙÕð ÷k SÕRú÷õ ûôv 	×ÑÐ 8Ô9ÞÙÕð üsO   ŠD&I
Ä1+H! ÅHÅ1AG?Ç
HÇH! Ç%I
Ç?
H	È	HÈ
HÈH! È!&IÉI
c                 ó€   ^^• [         R                  " 5       m[        R                  5       m[        SUU4S jj5       n U $ )a�  Snapshot the current OTel context so it can be re-attached in another task.

The streaming continuation composite opens each segment's `request_stream` lazily,
in the *consumer* task that iterates the stream, whereas the `chat` span is opened
by `wrap_model_request` in a separate task. Those tasks don't share an OTel context,
so without re-attaching, span updates driven by `get_current_span()` (e.g.
`FallbackModel` recording the resolved inner model) would land on the wrong span.

Returns a factory that yields a context manager re-attaching the captured context;
the composite enters it around each segment without depending on OpenTelemetry itself.
c               3  óv  >#   • [         R                  " 5       n [        R                  5       n[         R                  " T5        [        R                  T5         S v •  [         R                  " U 5        [        R                  U5        g ! [         R                  " U 5        [        R                  U5        f = f7fr½   )Úotel_contextÚget_currentrT   rV   Úattachrs   )ÚpreviousrJ  ÚcapturedÚcaptured_include_contents     €€rR   Úattach_captured_contextÚ8capture_current_context.<locals>.attach_captured_contextí  s‰   øé € ô  ×+Ò+Ó-ˆÜ#6×#:Ñ#:Ó#<Ð Ü×Ò˜HÔ%ô 	×ÑÐ 8Ô9ð	>Ûä×Ò Ô)Ü×#Ñ#Ð$<Õ=øô ×Ò Ô)Ü×#Ñ#Ð$<Õ=üs   ƒAB9ÁB	 Á,B9Â	-B6Â6B9)r  úGenerator[None])rN  rO  rT   rV   r	   )rT  rR  rS  s    @@rR   Úcapture_current_contextrW  Ú  s>   ù€ ô ×'Ò'Ó)€Hô
  3×6Ñ6Ó8Ðä÷>ó ð>ð* #Ð"rQ   c                ó²   • SSK Jn  SSKJn  U(       a)  UR	                  X5      nU(       a  UR                  U5      $ [        U 5      nUb  UR                  $ S$ )aš  Get the joined instructions string for the current request.

When `model_request_parameters` is provided (normal model request flow), returns
the joined content of `instruction_parts` which already includes prompted output
instructions and is properly sorted.

Falls back to reading `ModelRequest.instructions` from message history when
`model_request_parameters` is not available (e.g. OTel span attributes).
r   )ÚInstructionPart)ÚModelN)r‰   rY  rà   rZ  Ú_get_instruction_partsÚjoinÚget_instructions_sourceÚinstructions)r¬   rÌ   rY  rZ  rc   Úsources         rR   Úget_instructionsr`    sS   € õ 5Ý(æØ×,Ñ,¨XÓPˆÞØ"×'Ñ'¨Ó.Ð.ô % XÓ.€FØ"(Ñ"4ˆ6×ÑÐ>¸$Ð>rQ   c                ó:  • SSK Jn  / n[        U 5       HH  n[        X15      (       d  M  UR	                  U5        [        U5      S:X  a    OUR                  c  MF  Us  $    [        U5      S:X  a-  US   nUS   n[        S UR                   5       5      (       a  U$ g)a”  The request in `messages` whose `instructions` are the ones in force for the current request.

Split out from `get_instructions` because the resume path needs the request itself, not just its
text: a `before_model_request` hook's rewrite has to land on the message that records the
instructions being echoed back, and stamping the wrong one would put instructions on a request
that was sent without any.
r   )r)   é   Nr$   c              3  ój   #   • U  H)  oR                   S :H  =(       d    UR                   S:H  v •  M+     g7f)ztool-returnzretry-promptN)Ú	part_kind)Ú.0Úps     rR   Ú	<genexpr>Ú*get_instructions_source.<locals>.<genexpr>I  s+   é € ÐpÒVoÐQR�{‰{˜mÑ+×L¨q¯{©{¸nÑ/LÔLÒVoùs   ‚13)	r‰   r)   Úreversedr‹   rü   Úlenr^  Úallrc   )r¬   r)   Úlast_two_requestsra   Úmost_recent_requestÚsecond_most_recent_requests         rR   r]  r]    s¢   € õ 2ð -/ÐÜ˜HÖ%ˆÜ�g×,Ó,Ø×$Ñ$ WÔ-ÜÐ$Ó%¨Ó*ÙØ×#Ñ#Ó/Ø’ñ &ô ÐÓ Ó"Ø/°Ñ2ÐØ%6°qÑ%9Ð"ô  ÑpÐVi×VoÒVoÓp×pÑpØ-Ð-àrQ   c                 óR   • [        5       n U [        L a  g[        U 5      =(       d    S$ )a  Return the W3C traceparent of the active OTel span, or None if no valid span is set.

Used as a fallback when the graph run was created without a span. In that case,
the agent run span is typically set by the Instrumentation capability via
`start_as_current_span` while the capability chain is executing, which is
exactly when consumers like `OnlineEvaluation` read the traceparent.
N)r   r   r#   )rX   s    rR   Úcurrent_otel_traceparentrp  O  s'   € ô Ó€DØŒ|ÒØÜ˜4Ó ×( DÐ(rQ   c                  ó²   • \ rS rSr% SrS\S'   S\S'   S\S'   S\S'   S\S'   S\S	'   S
rS\S'   SrS\S'   SrS\S'   \	SS j5       r
SS jrSS jrSS jrSrg)ÚInstrumentationNamesi]  zMConfiguration for instrumentation span names and attributes based on version.rž   Úagent_run_span_nameÚagent_name_attrÚtool_span_nameÚtool_arguments_attrÚtool_result_attrÚoutput_tool_span_namezpydantic_ai.tool.deferral.namezClassVar[str]Útool_deferral_name_attrz"pydantic_ai.tool.deferral.metadataÚtool_deferral_metadata_attrzpydantic_ai.tool.failure_stageÚtool_failure_stage_attrc           	     ó:   • US:X  a  U " SSSSSSS9$ U " S	S
SSSSS9$ )zÆCreate instrumentation configuration for a specific version.

Args:
    version: The instrumentation version (2 or 3+)

Returns:
    InstrumentationConfig instance with version-appropriate settings
rb  z	agent runrl   zrunning toolÚtool_argumentsÚtool_responsezrunning output function)rs  rt  ru  rv  rw  rx  Úinvoke_agentr1   Úexecute_toolzgen_ai.tool.call.argumentszgen_ai.tool.call.resultrH   )ÚclsÚversions     rR   Úfor_versionÚ InstrumentationNames.for_versiont  sK   € ð �a‹<ÙØ$/Ø ,Ø-Ø$4Ø!0Ø&?ñð ñ Ø$2Ø 3Ø-Ø$@Ø!:Ø&4ñð rQ   c                óD   • U R                   S:X  a  SU 3$ U R                   $ )z}Get the formatted agent span name.

Args:
    agent_name: Name of the agent being executed

Returns:
    Formatted span name
r  zinvoke_agent )rs  )r  rl   s     rR   Úget_agent_run_span_nameÚ,InstrumentationNames.get_agent_run_span_name‘  s+   € ð ×#Ñ# ~Ó5Ø" : ,Ð/Ð/Ø×'Ñ'Ð'rQ   c                óD   • U R                   S:X  a  SU 3$ U R                   $ )zzGet the formatted tool span name.

Args:
    tool_name: Name of the tool being executed

Returns:
    Formatted span name
r€  úexecute_tool )ru  ©r  rì   s     rR   Úget_tool_span_nameÚ'InstrumentationNames.get_tool_span_namež  s+   € ð ×Ñ .Ó0Ø" 9 +Ð.Ð.Ø×"Ñ"Ð"rQ   c                óD   • U R                   S:X  a  SU 3$ U R                   $ )z�Get the formatted output tool span name.

Args:
    tool_name: Name of the tool being executed

Returns:
    Formatted span name
r€  r‰  )rx  rŠ  s     rR   Úget_output_tool_span_nameÚ.InstrumentationNames.get_output_tool_span_name«  s+   € ð ×%Ñ%¨Ó7Ø" 9 +Ð.Ð.Ø×)Ñ)Ð)rQ   rH   N)r‚  rD   r  r'   )rl   rž   r  rž   )rì   rž   r  rž   )rJ   rK   rL   rM   rN   rO   ry  rz  r{  Úclassmethodrƒ  r†  r‹  rŽ  rP   rH   rQ   rR   rr  rr  ]  sw   ‡ áWð ÓØÓð ÓØÓØÓð Óð .NÐ˜]ÓMØ1UÐ ÓUð .NÐ˜]ÓMàóó ðô8(ô#÷*rQ   rr  )rX   r   r  rF   )r  rÓ   )rv   r   rw   r.   r  rb   )rv   r   r’   zset[int]r  rb   )rv   r   r  rž   )rv   rb   r  rd   )rw   r.   ra   r(   r  rd   )rw   r.   r¬   úSequence[ModelMessage]r   rf   r  rF   )r³   ú
str | Noner  údict[str, AttributeValue]r½   )rº   rž   r³   r’  r  r“  )rÀ   r+   r  r“  )rÆ   r’  rÇ   úAttributeValue | NonerÈ   r”  r  r“  )rÌ   r-   rG   rF   r  r“  )rÙ   r   r  zdict[str, Any] | None)rÌ   r-   r  r   )r  z#TypeAdapter[ModelRequestParameters])rã   zModelSettings | Noner  r“  )rî   r*   rÚ   r-   r  r  )rÌ   r-   r  rÕ   )rî   r*   rÈ   r”  r  úPriceCalculation | Noner  r“  )rî   r*   r  r•  )
rX   r   r!  ÚBaseExceptionrG   rF   r  rF   r  r  )rX   r   r!  r–  rG   rF   r  r  )rX   r   rG   rF   r  rV  )rw   r.   rF  r,   r+  zMessageJsonCache | Noner  z>Generator[tuple[_FinishModelRequestSpan, ModelRequestContext]])r  z*Callable[[], AbstractContextManager[None]])r¬   r‘  rÌ   zModelRequestParameters | Noner  r’  )r¬   r‘  r  zModelRequest | None)r  r’  )yÚ
__future__r   rö   r—   Úcollections.abcr   r   r   r   Ú
contextlibr   r	   Úcontextvarsr
   Údataclassesr   r   Ú	functoolsr   Útypingr   r   r   r   r   r   r   Úurllib.parser   Úopentelemetryr   rN  Úopentelemetry.baggager   Úopentelemetry.tracer   r   r   r   r   r   Úopentelemetry.util.typesr   Úpydanticr   r    Úpydantic_corer!   r"   Úpydantic_graph._utilsr#   Ú_genai_pricesr%   Úgenai_prices.typesr&   Útyping_extensionsr'   r‰   r(   r)   r*   rà   r+   r,   r-   Úpydantic_ai.models.instrumentedr.   Úpydantic_ai.settingsr/   ÚDEFAULT_INSTRUMENTATION_VERSIONrh   ri   rj   r¹   r¾   r¸   r8   rO   rš   r�   ÚTOKEN_HISTOGRAM_BOUNDARIESÚ(TIME_TO_FIRST_CHUNK_HISTOGRAM_BOUNDARIESrB   rT   rZ   r\   r_   r×   rD   rf   ro   rŽ   ry   rr   rŸ   r¦   rª   r®   r¶   r»   rÁ   rÉ   rÑ   rÎ   rÍ   rÝ   rä   rð   r   r  r  r  r  r'  r)  rK  rW  r`  r]  rp  rr  rH   rQ   rR   Ú<module>r®     sV  ðÞ "ã Û ß BÓ Bß =Ý "ß *Ý ß S× SÑ SÝ !å 1Ý -ß b× bÝ 3ß ,ß =å 1å ,æÝ3Ý&çNÑNß]Ñ]ÝGÝ2à"#Ð Ø Dà,Ð Ø+Ð Ø6Ð à)Ð Ø!7Ð Ø!7Ð ðð ð 
ó ð& ˜#Ò˜sÓ#€Ø! #Ò& s±:ÈXÑ3VÑWÐ ð yÐ ð,Ð (ñ
 �$Ñ÷ð ó ðñ 9CÐCTÐ^bÑ8cÐ Ð5Ó cð
ôoñ 5?Ð?TÐ^bÑ4cÐ Ð1Ó cðñ �Ñ÷Að Aó ðAð  # 3Ð(9Ð#9Ñ:Ð �)Ó :ðôð "8Ð ôFô:/!ôd
/ô
AôMðØ%ðØ1GðØP`ðà	ôô8ö0ôðØðà(ðð *ðð ô	ð$ RVñKØ4ðKØJNðKàõKôô67ð  ó/ó ð/ôô7ô0ð@ 26ðØðà)ðð /ðð õ	ô0ôg˜hô gð bf÷ mô:
ð óó ðð" ð
 37ñ	sØ%ðsà(ðsð 0ð	sð
 Dôsó ðsôl)#ðZ aeð?Ø$ð?Ø@]ð?àõ?ô2-ô`)ñ �$Ñ÷X*ð X*ó ñX*rQ   