
    `gj1                       U d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	m
Z
mZ ddlmZmZmZ  ej                   e      Z	 ddlmZmZ e
 G d d             Z ej0                         Zi Zd	ed
<   dZda ej<                  d      ZdZ dZ!dddZ"ded<   dLdMdZ#dNdZ$dOdZ%dPdZ& e'       Z(dQdZ)dRdZ*dSdZ+dTdZ,ddd	 	 	 	 	 	 	 	 	 dUdZ-dVdZ.dWd Z/dXd!Z0dYd"Z1dZd#Z2d[d$Z3d\d%Z4dd&d]d'Z5ddd(d^d)Z6ddd*d+	 	 	 d_d,Z7d`d-Z8ddddd.	 	 	 	 	 	 	 	 	 dad/Z9dbd0Z:dcd1Z;ddd2Z<ded3Z=ddd	 	 	 	 	 	 	 	 	 	 	 dfd4Z>dddd5	 	 	 	 	 	 	 	 	 dgd6Z?ddddd7	 	 	 	 	 dhd8Z@did9ZAdjd:ZBdd;dkd<ZCdld=ZDdmd>ZEdddddddddd?ddddd@	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dndAZFddddddddddd?ddddddddddB	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dodCZGddddddddddDddddddddE	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dpdFZHddddddddG	 	 	 	 	 	 	 	 	 	 	 dqdHZIdddddddddI	 	 	 	 	 	 	 	 	 	 	 	 	 drdJZJdjdKZKy# e$ r dZdZY w xY w)su\  langfuse — Hermes plugin for Langfuse observability.

Traces Hermes conversations, LLM calls, and tool usage to Langfuse.

Activation is handled by the Hermes plugin system — standalone plugins only
load when listed in ``plugins.enabled`` (via ``hermes plugins enable
observability/langfuse`` or ``hermes tools → Langfuse Observability``). At
runtime the plugin also requires the ``langfuse`` SDK and credentials; if
either is missing the hooks are inert.

Required env vars (set via ``hermes tools`` or ~/.hermes/.env):
  HERMES_LANGFUSE_PUBLIC_KEY  - Langfuse project public key (pk-lf-...)
  HERMES_LANGFUSE_SECRET_KEY  - Langfuse project secret key (sk-lf-...)
  HERMES_LANGFUSE_BASE_URL    - Langfuse server URL (default: https://cloud.langfuse.com)

Optional env vars:
  HERMES_LANGFUSE_ENV         - environment tag (e.g. "production", "local")
  HERMES_LANGFUSE_RELEASE     - release/version tag
  HERMES_LANGFUSE_SAMPLE_RATE - sampling rate 0.0–1.0 (default: 1.0)
  HERMES_LANGFUSE_MAX_CHARS   - max chars per field (default: 12000)
  HERMES_LANGFUSE_DEBUG       - set to "true" for verbose logging
    )annotationsN)	dataclassfield)AnyDictOptional)Langfusepropagate_attributesc                      e Zd ZU ded<   ded<   ded<    ee      Zded<    ee      Zded	<    ee      Zd
ed<    ee	      Z
ded<    eej                        Zded<   y)
TraceStatestrtrace_idr   root_ctx	root_span)default_factoryzDict[str, Any]generationstoolszDict[str, list]pending_tools_by_namelist[dict[str, Any]]turn_tool_callsfloatlast_updated_atN)__name__
__module____qualname____annotations__r   dictr   r   r   listr   timer        Z/root/.hermes/venv/lib/python3.12/site-packages/plugins/observability/langfuse/__init__.pyr   r   +   sb    MMN"'"=K=!$7E>7-24-H?H,1$,GO)G"499=OU=r!   r   zDict[str, TraceState]_TRACE_STATE   z^\s*(\d+)\|(.*)$      zpk-lf-zsk-lf-)HERMES_LANGFUSE_PUBLIC_KEYHERMES_LANGFUSE_SECRET_KEYzDict[str, str]_LANGFUSE_KEY_PREFIXES c                ^    t         j                  j                  | |      j                         S )N)osenvirongetstrip)namedefaults     r"   _envr2   S   s     ::>>$(..00r!   c                 T    | D ]#  }t        |      j                         }|s|dv c S  y)N>   1onyestrueF)r2   lower)namesr0   values      r"   	_env_boolr;   W   s7     7T
  "6667 r!   c                     t        d      S )NHERMES_LANGFUSE_DEBUG)r;   r    r!   r"   _debug_enabledr>   _   s    ,--r!   c                F    t               rt        j                  d|        y y )NzLangfuse tracing: %s)r>   loggerinfomessages    r"   _debugrD   c   s    *G4 r!   c                \    | syt        |       dk  rt        |       S t        | dd dz         S )ao  Return a brief, log-safe preview of a credential value.

    Keeps enough characters to disambiguate common placeholders
    (``placeholder``, ``test-key``, ``your-key``) without echoing a
    real secret in full if an operator pasted one into the wrong env
    var.  Used only for the once-per-process placeholder-detection
    warning in :func:`_get_langfuse`.
    z<empty>   N   z...)lenrepr)r:   s    r"   _redact_key_previewrJ   q   s6     
5zRE{bq	E!""r!   c                    t         j                  | d      }|sy|j                  |      ry|  dt        |       d|dS )u  Return an error message if ``value`` is not a real Langfuse key.

    Returns ``None`` when the value matches the documented Langfuse
    prefix for ``env_name``, or when no prefix is registered for the
    name (in which case we trust the operator).  When validation
    fails the returned string is suitable for direct inclusion in a
    single log line — it names the env var and shows a safe preview.
    r*   N=z (expected z prefix))r)   r.   
startswithrJ   )env_namer:   expecteds      r"   _validate_langfuse_keyrP      sU     &))(B7H!*A)%01 2L	*r!   c                 B   t         t        u ryt         t         S t        t        a yt        d      xs t        d      } t        d      xs t        d      }| r|st        a yt	        d|       t	        d|      fD cg c]  }|r| }}|r,t
        j                  ddj                  |             t        a yt        d      xs t        d	      xs d
}t        d      xs t        d      }t        d      xs t        d      }t        d      }| ||d}|r||d<   |r||d<   |r	 t        |      |d<   	 t        di |a t         S c c}w # t        $ r t
        j                  d|       Y 8w xY w# t        $ r&}	t
        j                  d|	       t        a Y d}	~	yd}	~	ww xY w)u  Return a cached Langfuse client, or ``None`` if unavailable.

    Activation of this plugin is controlled by the Hermes plugin system —
    this function only handles the runtime-availability gate (SDK installed
    + credentials present). The result is cached: on the first call we try
    to construct a client, and every subsequent call returns that client
    (or fast-returns ``None`` if init failed).
    Nr'   LANGFUSE_PUBLIC_KEYr(   LANGFUSE_SECRET_KEYzLangfuse plugin: credentials look like placeholders, traces will NOT be emitted (%s). Set real Langfuse keys (pk-lf-... / sk-lf-...) or unset HERMES_LANGFUSE_PUBLIC_KEY / HERMES_LANGFUSE_SECRET_KEY to silence this warning.z; HERMES_LANGFUSE_BASE_URLLANGFUSE_BASE_URLzhttps://cloud.langfuse.comHERMES_LANGFUSE_ENVLANGFUSE_ENVHERMES_LANGFUSE_RELEASELANGFUSE_RELEASEHERMES_LANGFUSE_SAMPLE_RATE)
public_key
secret_keybase_urlenvironmentreleasesample_ratez&Invalid HERMES_LANGFUSE_SAMPLE_RATE=%rz(Could not initialize Langfuse client: %sr    )_LANGFUSE_CLIENT_INIT_FAILEDr	   r2   rP   r@   warningjoinr   
ValueError	Exception)
r[   r\   msgplaceholder_issuesr]   r^   r_   r`   kwargsexcs
             r"   _get_langfuserk      s    <'#'23Rt<Q7RJ23Rt<Q7RJ:' ##?L"#?L
  	  $ II()	
 (./l48K3LlPlH,-En1EK,-I6H1IG45K ! F
  +}#y	R$)+$6F=!#-f- ]H  	RNNC[Q	R
  A3G's0   <E%E
 4E/ 
E,+E,/	F8FFc                L    | rd|  S |rd| S dt        j                          S )z?The task/session/thread prefix shared by every trace-key shape.ztask:zsession:zthread:)	threading	get_ident)task_id
session_ids     r"   _scope_prefixrq      s9    wi  *&&Y((*+,,r!   turn_idapi_request_idc               n    |rt        | |       d| S |rt        | |       d| S | r| S t        | |      S )a  Build a stable in-process trace scope key for one agent turn.

    Older Hermes paths only expose ``task_id``/``session_id``. Newer paths
    pass ``turn_id`` and ``api_request_id`` in LLM/tool hooks; when present,
    they must scope trace state so concurrent requests sharing one task/session
    never collide. ``turn_id`` is preferred over ``api_request_id`` so the
    turn-level ``post_llm_call`` hook (which carries ``turn_id`` but no
    ``api_request_id``) resolves to the same key as the request-level hooks.
    z:turn:z:api:)rq   )ro   rp   rs   rt   s       r"   
_trace_keyrv      sT      45VG9EE45U>:JKK *--r!   c                V    | d d j                         }|j                  d      xr d|v S )N   data:z;base64,)r8   rM   )r:   prefixs     r"   _is_base64_data_urir{     s1    4C[ FW%>**>>r!   c                    d| v r| j                  dd      d   nd}|j                  d      r|dd  j                  dd      d   nd}d|xs d d	t        |       d
S )N,   r   ry      ;r*   data_uriT)type
media_typeomittedlength)splitrM   rH   )r:   headerr   s      r"   _redact_data_urir     sk    '*e|U[[a #F060A0A'0J!!#q)!,PRJ (De*	 r!   c                ~    t        |       rt        |       S t        |       |k  r| S | d | dt        |       |z
   dz   S )Nz... [truncated  chars])r{   r   rH   )r:   	max_charss     r"   _truncate_textr     sM     5!&&
5zY)Ui1G0HPPPr!   c                   | j                         }t        |      dk  s|d   dvs|d   dvrt        |      dk  s|d   dvr| S 	 t        j                         j	                  |      \  }}t        |t        t        f      s| S ||d  j                         }|s|S |j                  d      rdnd}t        |t              rt        |      }||vr|nd}|||<   |S d	|||iS # t
        $ r | cY S w xY w)
N   r   z{[z}]z[Hint:_hint_trailing_textdata)
r/   rH   jsonJSONDecoder
raw_decoderf   
isinstancer   r   rM   )r:   strippedparsedidxtrailinghint_keymergedkeys           r"   _maybe_parse_json_stringr   )  s   {{}H
8}qHQKt3x|47Ox=14 7L&&(33H= ftTl+~##%H"--h7w=MH&$f"&0h6FsFHh//!  s   &C C-,C-c                    t        | t              sy| j                  d      }t        |t              xr* d| v xr$ d| v xr d| v xr d| v xr | j                  d       S )NFcontenttotal_lines	file_size	is_binaryis_imageerror)r   r   r.   r   )r:   r   s     r"   _looks_like_read_file_payloadr   C  sz    eT"ii	"G7C  	#U"	#5 	# 5 	# %		#
 		'""r!   c                   t        | t              r| sg S g }| j                         D ]X  }t        j	                  |      }|sg c S |j                  t        |j                  d            |j                  d      d       Z |S )Nr~   r   )linetext)r   r   
splitlines_READ_FILE_LINE_REmatchappendintgroup)r   linesraw_liner   s       r"   _parse_read_file_linesr   Q  s{    gs#7	E&&( "((2IA'KKN
 		 Lr!   c                    t        |       t        t        z   k  rd| iS | d t         | t         d  t        |       t        z
  t        z
  dS )Nr   )headtailomitted_line_count)rH   _READ_FILE_HEAD_LINES_READ_FILE_TAIL_LINES)r   s    r"   _build_read_file_previewr   a  sZ    
5z+.CCD ,,-,,-.!%j+@@CXX r!   argsc                  i }t        |t              rt|j                  d      }|j                  d      }|j                  d      }t        |t              r|r||d<   t        |t              r||d<   t        |t              r||d<   t        | j                  dd            }|r-|d   d   |d   d   t        |      d	|d
<   t        |      |d<   n(| j                  d      rd| j                  dd      i|d<   dD ]  }|| v s| |   ||<    | j                  d      }t        |t              r|rdt        |      d|d<   |S )Npathoffsetlimitr   r*   r   r   r   )startendcountreturned_linescontent_previewr   )r   r   	truncatedr   r   hint_warning	mime_type
dimensionssimilar_filesr   base64_contentT)r   r   )r   r   r.   r   r   r   rH   r   )	r:   r   
normalizedr   r   r   r   r   r   s	            r"   _normalize_read_file_payloadr   l  s]   !#J$xx(#!dC T!%Jvfc"#)Jx eS!"'Jw"599Y#;<E1Xf%9V$Z(

#$
 )A(G
$%	9	EIIi,)

$% ) %<#CjJsO)  YY/0N.#&>.)(

#$
 r!   	tool_namer   c               N    t        |       rt        | |dk(  r|      S d       S | S )N	read_filer   )r   r   )r:   r   r   s      r"   _normalize_payloadr     s8    $U++"k1
 	
7;
 	
 Lr!   Fr   depthparse_json_stringsc               D   ||nt        t        dd      xs d      }|dkD  ry| t        | t         t        t        f      r| S t        | t
              rdt        |       dS t        | t              r,|rt        |       }|| urt        |||d      S t        | |      S t        | t              rgt        |       }|| urt        ||||      S t        | j                               d d	 D ci c]!  \  }}t        |      t        |||d
z   |      # c}}S t        | t        t        t         f      r,t        |       d d	 D cg c]  }t        |||d
z   |       c}S t#        | d      rt        t%        |       ||d
z   |      S t        t'        |       |      S c c}}w c c}w )NHERMES_LANGFUSE_MAX_CHARS12000   z<max-depth>bytes)r   rH   Tr   2   r~   __dict__)r   r2   r   r   boolr   rH   r   r   _safe_valuer   r   r   r   itemstuplesethasattrvarsrI   )r:   r   r   r   r   r   kvs           r"   r   r     s   &2	DA\^e<f<qjq8rIqy}
53t*<=%E
33%-e4FU""6Ye`deeeY//%'.
U"zYe`rss U[[]+CR0
1 FKYeai\noo
 	
 %$s+, %["%
 YeaiTfg
 	
 uj!4;)519astt$u+y11


s   *&F?Fc                    t        | t              sy t        |       D ]F  }t        |t              s|j	                  d      dk(  s)dt        |j	                  d            dc S  y )Nroleuserr   r   r   )r   r   reversedr   r.   r   )messagesrC   s     r"   _extract_last_user_messager     s`    h%H% gt$V)<)F&w{{9'=>  r!   request_messagesr   conversation_historyuser_messagec                R    | ||fD ]  }t        |t              s|c S  |g S d|dgS )Nr   r   )r   r   )r   r   r   r   	candidates        r"   _coerce_request_messagesr     sF     '2FG 	i& 	566r!   c                   t        | t              sg S g }| dd  D ]  }t        |t              s|j                  d      }|t	        |j                  d      |dk(        d}|dk(  rS|j                  d      r|j                  d      |d<   |j                  d      rt	        |j                  d            |d<   |j                  d	      rt	        |j                  d	      d
      |d	<   |j                  |        |S )Nir   r   toolr   r   tool_call_idr0   
tool_callsT)r   r   r   r.   r   r   )r   
serializedrC   r   items        r"   _serialize_messagesr     s    h%	JCD>  '4({{6""I&$(FN
 6>{{>*'.{{>'B^${{6"*7;;v+>?V;;|$!,W[[-F[_!`D$% & r!   c           
         | sg S g }| D ]r  }t        |dd       }|rt        |dd       nd }|rt        |dd       nd }t        |d      }|j                  t        |dd       t        |dd       xs d||||dd	       t |S )
Nfunctionr0   	argumentsFr   idr   )r0   r   )r   r   r0   r   r   )getattrr   r   )r   r   	tool_callfnr0   r   safe_argumentss          r"   _serialize_tool_callsr    s    	J 	Y
D1,.wr64(D68GBT2d	$Y5I)T40Ivt4B
'+	
 		 r!   c           	         t        t        | dd             t        t        | dd             t        t        | dd             dS )Nr   	reasoningr   r   r  r   )r   r   r  rB   s    r"   _serialize_assistant_messager    s?    ww	4@A +t!DE+GG\4,PQ r!   c                  i }i }t        | dd       }|s||fS 	 ddlm}m}	  |	|||      }
|
j                  |
j
                  d}|
j                  r|
j                  |d<   |
j                  r|
j                  |d<   |
j                  r|
j                  |d<    |||
||d	
      }|j                  T	 ddlm
} ddlm}  |d      } ||||      }|r|j                  :|
j                  r.t         ||
j                        |j                  z  |z        |d<   |j                  :|
j
                  r.t         ||
j
                        |j                  z  |z        |d<   |j                   :|
j                  r.t         ||
j                        |j                   z  |z        |d<   |j"                  S|
j                  rGt         ||
j                        |j"                  z  |z        |d<   nt        |j                        |d<   ||fS # t$        $ r t        |j                        |d<   Y 'w xY w# t$        $ r}t'        d|        Y d }~||fS d }~ww xY w)Nusager   )estimate_usage_costnormalize_usage)providerapi_modeinputoutputcache_read_input_tokenscache_creation_input_tokensreasoning_tokensr*   r  r]   api_key)get_pricing_entryDecimal1000000r  r]   r  r  totalzusage normalization failed: )r   agent.usage_pricingr  r  input_tokensoutput_tokenscache_read_tokenscache_write_tokensr  
amount_usdr  decimalr  input_cost_per_millionr   output_cost_per_millioncache_read_cost_per_millioncache_write_cost_per_millionrf   rD   )responser  r  modelr]   usage_detailscost_details	raw_usager  r  	canonicalcostr  r  _ONE_Mentryrj   s                    r"   _usage_and_costr1    s   $&M%'L'40Il**25L#I8T	 ++--
 &&7@7R7RM34'';D;W;WM78%%090J0JM,-"
 ??&?A+ +)%(XV33?IDZDZ05gi>T>T6UX]XtXt6tw}6}0~W-44@YE\E\16wy?V?V7WZ_ZwZw7w  {A  8A  2BX.88DIdIdBGPYPkPkHlot  pQ  pQ  IQ  TZ  IZ  C[%>?99E)JfJfFKGT]TpTpLqty  uW  uW  MW  Z`  M`  Ga%BC,1$//,BL) ,&&  ?(-doo(>W%? 5-cU344,&&5s7   BH/ 1EH !H,)H/ +H,,H/ /	I8IIc       
   	     n   |j                  |xs d d|xs |        }t        |      }d||	|
||||d}d|i}|r||d<   t        F	 t        |xs | ddd	g
      5  |j                  |dd||d      }|j	                         }d d d        n'|j                  |dd||d      }|j	                         }	 j                  |       t        d| d|         t        |      S # 1 sw Y   cxY w# t
        $ r* |j                  |dd||d      }|j	                         }Y pw xY w# t
        $ r Y lw xY w)Nsessionlessz::)seedhermes)sourcero   rs   rt   platformr  r)  r  r   rp   zHermes turnlangfuse)rp   
trace_nametagschainF)trace_contextr0   as_typer  metadataend_on_exit)r  zstarted trace z for )r   r   r   )	create_trace_idr   r
   start_as_current_observation	__enter__rf   set_trace_iorD   r   )task_keyro   rp   r7  r  r)  r  r   clientrs   rt   r   trace_inputr>  	trace_ctxr   r   s                    r"   _start_root_tracerH  [  s    %%j.IM-J"WM`X`La+b%cH,X6K(	H ",X 6I",	,'	-%%1(
+ 1
 ">>"+&#%% % ?  %..0	12 66# 7 
 &&(	[1 ^H:U8*56x(iPPS1 1  		-::'"!!! ; H !**,I		-.  s<   C2 (C&C2 5D( &C/+C2 20D%$D%(	D43D4)r>  r)  model_parametersc               L    | j                   j                  ||||xs i ||      S )N)r0   r=  r  r>  r)  rI  )r   start_observation)staterE  r0   r=  input_valuer>  r)  rI  s           r"   _start_child_observationrN    s6     ??,,R) -  r!   )r  r>  r*  r+  c                   | y 	 i }|||d<   |r||d<   |r||d<   |r||d<   |r | j                   di | | j                          y # t        $ r}t        d|        Y d }~y d }~ww xY w)Nr  r>  r*  r+  zend observation failed: r    )updater   rf   rD   )observationr  r>  r*  r+  update_kwargsrj   s          r"   _end_observationrS    s    1(*&,M(#(0M*%-:M/*,8M.)K// 1)#/001s   AA 	A)A$$A)c                    |j                   s| S t        | t              rt        |       nd| i}t        |j                         |d<   |S )Nr   r   )r   r   r   r   )r  rL  r   s      r"   _merge_trace_outputrU    sC      '5T&\Iv;NF 5 56F<Mr!   c                 F   t        t              t        dz
  z
  } | dk  ryt        t        j	                         d       d|  }|D ]6  \  }}t        j                  |d       	 |j                  j                          8 y# t        $ r}t        d|        Y d}~Vd}~ww xY w)uX  Drop least-recently-updated trace state to make room for a new entry.

    Caller MUST hold ``_STATE_LOCK`` and call this immediately before inserting
    one new entry. Bounds the leak from turns that never reach ``_finish_trace``
    (interrupted / tool-only final step / empty final content), whose unique
    per-turn key would otherwise linger forever. We evict down to
    ``_MAX_TRACE_STATE - 1`` so that the about-to-be-added entry leaves the dict
    at ``_MAX_TRACE_STATE`` — a true ceiling. The evicted entry's root span is
    ended so it is not left dangling on the Langfuse side.
    r~   r   Nc                     | d   j                   S )Nr~   )r   )kvs    r"   <lambda>z%_evict_stale_locked.<locals>.<lambda>  s    18M8M r!   )r   zevict stale trace failed: )
rH   r#   _MAX_TRACE_STATEsortedr   popr   r   rf   rD   )overstaler   rL  rj   s        r"   _evict_stale_lockedr_    s     | 01 45Dqy<%%'-MNuPTUE 7
Ud#	7OO!7  	7/u566	7s   "A??	B BB r  c               &   t               }|y t        5  t        j                  | d       }d d d        y 	 |j                  j                         D ]  }t        |        |j                  j                         D ]  }t        |        |j                  j                         D ]  }|D ]  }t        |         t        ||      }|8|j                  j                  |       |j                  j                  |       |j                  j                          	 |j!                          y # 1 sw Y   xY w# t        $ r}t        d|        Y d }~;d }~ww xY w# t        $ r Y y w xY w# 	 |j!                          w # t        $ r Y w w xY wxY w)Nr`  zfinish trace failed: )rk   _STATE_LOCKr#   r\  r   valuesrS  r   r   rU  r   rC  rP  r   rf   rD   flush)rD  r  rE  rL  rQ  queuefinal_outputrj   s           r"   _finish_tracerg    sz   _F~	 1  401} ,,335 	*K[)	* ;;--/ 	*K[)	*00779 	.E$ . -.	. +659#OO(((=OO"","7	LLN-1 1$  .&se,--.
  			LLN 		sk   D.C%D; E .D8;	EEE. EE. 	E+*E+.F0F F	F
FFFc                .    t        t        | dd             S )Nr   )r   r   rB   s    r"   _assistant_has_tool_callsri    s    t455r!   c                     t        | xs d      S )Nr   )r   )api_call_counts    r"   _request_keyrl    s    ~"##r!   r   )ro   rp   r7  r)  r  r]   r  rk  r   	turn_typer   r   rs   rt   c                F   t        |t              sy t               }|y t        | |||      }t        5  t
        j                  |      }|)t        || |||||||||      }t                |t
        |<   t        j                         |_
        d d d        y # 1 sw Y   y xY w)Nrr   
ro   rp   r7  r  r)  r  r   rE  rs   rt   )r   r   rk   rv   rb  r#   r.   rH  r_  r   r   )ro   rp   r7  r)  r  r]   r  rk  r   rm  r   r   rs   rt   _rE  rD  rL  s                     r"   on_pre_llm_callrq  	  s     h%_F~ %	H 
 ,  *=%%!!!!-E  !%*L" $		%, , ,s   ABB )ro   rp   r7  r)  r  r]   r  rk  r   r   rm  message_count
tool_countapprox_input_tokensrequest_char_count
max_tokensr   r   rs   rt   c                   t               }|y t        ||	||      }t        | |||      }t        |      }t        5  t
        j                  |      }|)t        || |||||||||      }t                |t
        |<   t        j                         |_
        |j                  j                  |d       }|t        |       t        ||d| dt        |      ||||d|||d      |j                  |<   d d d        y # 1 sw Y   y xY w)	Nr   rr   ro  z	LLM call 
generation)r  r7  r  r]   )r  r  )rE  r0   r=  rM  r>  r)  rI  )rk   r   rv   rl  rb  r#   r.   rH  r_  r   r   r   r\  rS  rN  r   )ro   rp   r7  r)  r  r]   r  rk  r   r   rm  rr  rs  rt  ru  rv  r   r   rs   rt   rp  rE  input_messagesrD  req_keyrL  previouss                              r"   on_pre_llm_requestr|  :  s:   0 _F~-)1!	N %	H >*G	 $
  *=%%!!!'-E  !%*L" $		$$(($7X&%=^,- +N;$$$$	 *2I&
'"-$
 $
 $
s   B7C==Dg        )ro   rp   r  r]   r  r)  rk  assistant_messager(  api_durationfinish_reasonr
  assistant_content_charsassistant_tool_call_countassistant_responsers   rt   c                "   t               }|y t        | |||      }t        |      }t        5  t        j                  |      }|r|j                  j                  |d       nd }d d d        y |t        |      }n@|t        |      d g d}n.|rd| dnd d |rt        |      D cg c]	  }dd| i c}ng d}|j                  d      r|j                  j                  |d          t        |dd       t        |||||	      \  }}nt        |t               r|r|j                  d
d      }|j                  dd      xs |j                  dd      }|j                  dd      }|j                  dd      }|j                  dd      }||d}|r||d<   |r||d<   |r||d<   i }	 ddlm} m}!m}" ddlm}#  |#d      }$ | |||||      }% |"|||      }&|&r|&j.                  &|r$t1         |#|      |&j.                  z  |$z        |d<   |&j2                  &|r$t1         |#|      |&j2                  z  |$z        |d<   |&j4                  &|r$t1         |#|      |&j4                  z  |$z        |d<   |&j6                  X|rVt1         |#|      |&j6                  z  |$z        |d<   n1 |!||%||d      }'|'j8                  t1        |'j8                        |d<   ni i }}t=        |j                  dg             xs |}(d|(i})|	r|	dkD  rt?        |	d      |)d <   |
r|
|)d!<   tA        |||||)"       |rtC        |      n|dkD  }*tE        |j                  d#            }+|*s|+rtG        ||$       y y y # 1 sw Y   xY wc c}w # t:        $ r Y w xY w)%Nrr   r  [r   r   tc_r   r
  )r  r  r)  r]   r  r   r  completion_tokensr   r!  r  r  r  r  )CanonicalUsager  r  r  r  )r  r  r   r!  r  r  r  r  r*   r  r  tool_call_count   api_duration_sr  )r  r*  r+  r>  r   r`  )$rk   rv   rl  rb  r#   r.   r   r\  r  r   ranger   extendr   r1  r   r   r  r  r  r  r#  r  r$  r   r%  r&  r'  r"  rf   rH   roundrS  ri  r   rg  ),ro   rp   r  r]   r  r)  rk  r}  r(  r~  r  r
  r  r  r  rs   rt   rp  rE  rD  rz  rL  rx  r  ir*  r+  _input_output_cache_read_cache_write
_reasoningr  r  r  r  r/  _cur0  _costrs  gen_metadata	has_toolshas_contents,                                               r"   on_post_llm_callr    sB    _F~%	H >*G	 M  *=BU&&**7D9
M }
*
 $-.?@		'();<4_ab @W237;\`[te<U6VWDCs),Wz|
 zz,$$VL%9: x$'3&5'
#| 
E4	 U
 >1-))OQ/T599=PRS3Tii 3Q7yy!5q9YY115

 7BM34;GM780:M,-	bb'Y'F #%"-#/!+C &ehRE//;,1'&/ED`D`2`ci2i,jL)00<-2773CeFcFc3cfl3l-mL*44@[>CGKDX[`[|[|D|  @F  EF  ?GL!:;55AlBGP\H]`e  aC  aC  IC  FL  IL  CML!>?+E3T\fhi##/,1%2B2B,CL) ')"|VZZb12O6OJ$5z#BLq().|Q)?%&(5_%#! AR)*;<XqtuXuIvzz),-Khv. %9]M M& XL  		s$   6M0*M=/D,N 0M:	NN)r   r   ro   rp   r   rs   rt   c                n   t               }|y t        ||||      }	t        5  t        j	                  |	      }
|

	 d d d        y t        |
|d|  dt        |      | |d      }|r||
j                  |<   n+|
j                  j                  | g       j                  |       d d d        y # 1 sw Y   y xY w)Nrr   zTool: r   )r   r   )rE  r0   r=  rM  r>  )rk   rv   rb  r#   r.   rN  r   r   r   
setdefaultr   )r   r   ro   rp   r   rs   rt   rp  rE  rD  rL  rQ  s               r"   on_pre_tool_callr    s     _F~%	H 
 V  *=V V /)%#D)#,lK
 (3EKK%''229bAHHUV V Vs   B+AB++B4)r   r   resultro   rp   r   rs   rt   c           	     D   t        ||||      }	d }
t        5  t        j                  |	      }|
	 d d d        y |r|j                  j                  |d       }
|
L|j                  j                  |       }|r/|j                  d      }
|s|j                  j                  | d        d d d        |
y t        |t              rt        |      }n|}t        || |      }t        |d      }|rt        5  t        j                  |	      }|[t        |j                        D ]C  }|j                  d      |k(  s||d<   |j                  d      }t        |t              r||d<    n d d d        t        |
|| t        |d      d	       y # 1 sw Y   xY w# 1 sw Y   2xY w)
Nrr   r   r   Tr   r   r  r   )r  r>  )rv   rb  r#   r.   r   r\  r   r   r   r   r   r   r   r   r   rS  )r   r   r  ro   rp   r   rs   rt   rp  rD  rQ  rL  re  result_valuesafe_result_valuer  function_payloads                    r"   on_post_tool_callr  2  s    %	H K	 E  *=E E ++//,=K//33I>E#iil//33ItDE &#/7%lidSL#LTJ  		 $$X.E !)%*?*?!@ I }}T*l:.?	(++4==+D(%&6=9J,X6		  (+dW[2\]IE E2		 		s$   F
A,F
2AF7.F
FFc                   | j                  dt               | j                  dt               | j                  dt               | j                  dt               | j                  dt               | j                  dt
               y )Npre_api_requestpost_api_requestpre_llm_callpost_llm_callpre_tool_callpost_tool_call)register_hookr|  r  rq  r  r  )ctxs    r"   registerr  h  sl     ');<(*:;no6o'78o'78&(9:r!   )r*   )r0   r   r1   r   returnr   )r9   r   r  r   )r  r   )rC   r   r  None)r:   r   r  r   )rN   r   r:   r   r  Optional[str])r  zOptional[Langfuse])ro   r   rp   r   r  r   )
ro   r   rp   r   rs   r   rt   r   r  r   )r:   r   r  r   )r:   r   r  dict[str, Any])r:   r   r   r   r  r   )r:   r   r  r   )r:   r   r  r   )r   r   r  r   )r   r   r  r  )r:   r  r   r   r  r  )r:   r   r   r   r   r   r  r   )
r:   r   r   zOptional[int]r   r   r   r   r  r   )r   r   r  r   )
r   r   r   r   r   r   r   r   r  r   )r   r   r  r   )r   r   r  r   )rC   r   r  r  )r(  r   r  r   r  r   r)  r   r]   r   r  z'tuple[dict[str, int], dict[str, float]])rD  r   ro   r   rp   r   r7  r   r  r   r)  r   r  r   r   r   rE  r	   rs   r   rt   r   r  r   )rL  r   rE  r	   r0   r   r=  r   rM  r   r>  Optional[dict]r)  r  rI  r  r  r   )rQ  r   r  r   r>  r  r*  r  r+  r  r  r  )r  r   rL  r   r  r   )r  r  )rD  r   r  r   r  r  )rC   r   r  r   )rk  r   r  r   ) ro   r   rp   r   r7  r   r)  r   r  r   r]   r   r  r   rk  r   r   r   rm  r   r   r   r   r   rs   r   rt   r   rp  r   r  r  ),ro   r   rp   r   r7  r   r)  r   r  r   r]   r   r  r   rk  r   r   r   r   r   rm  r   rr  r   rs  r   rt  r   ru  r   rv  r   r   r   r   r   rs   r   rt   r   rp  r   r  r  )&ro   r   rp   r   r  r   r]   r   r  r   r)  r   rk  r   r}  r   r(  r   r~  r   r  r   r
  r   r  r   r  r   r  r   rs   r   rt   r   rp  r   r  r  )r   r   r   r   ro   r   rp   r   r   r   rs   r   rt   r   rp  r   r  r  )r   r   r   r   r  r   ro   r   rp   r   r   r   rs   r   rt   r   rp  r   r  r  )L__doc__
__future__r   r   loggingr,   rerm   r   dataclassesr   r   typingr   r   r   	getLoggerr   r@   r8  r	   r
   rf   r   Lockrb  r#   r   rZ  ra   compiler   r   r   r)   r2   r;   r>   rD   objectrb   rJ   rP   rk   rq   rv   r{   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r1  rH  rN  rS  rU  r_  rg  ri  rl  rq  r|  r  r  r  r  r    r!   r"   <module>r     s"  , #   	 	   ( & &			8	$ 7 > > > inn&(# (   RZZ 34    #+"**  1.5 x# (Od- ... 	.
 . 	.8?

Q04  HL 1h 8:t  ;?Q+02$(2582B	 ! $77 7 	7
 7 74,;'@ &(r@Q #@Q/2@Q<D@Q"@Q9<@QFP@QH KO48]a
*-
9G
$1
LZ
fi
 9=Y]59Z^1$21IW1cg1*70 37 @6$ ')BPRac$&B*+TTZ04$#%R	.,!.,25.,FI.,$'.,7:.,NQ., +.., EH., !	., 8;	., GJ	., OS	.,f    $+O
O
 O
 	O

 O
 O
 O
 O
 O
 O
 O
 O
 O
 O
 O
  !O
" #O
$ %O
& 'O
( )O
* +O
, 
-O
. 
/O
d (*RQSeg%'bPQ.2D+.R"&q67SW$&bC/"C/03C/JMC/(+C/>AC/ $)C/ @CC/  	C/ BE	C/
 14C/
 NQC/ "C/ 9<C/ C/ #'C/L *,b')r$&bV!$V9<V!V8;VGJVOSV@ +-$d%'2SU%'r3"3583MP3"39<3HK3PT3l	;E"   H s   I 	I%$I%