+
    iHàj   ã                  óž   € R t ^ RIHt ^ RIHtHt RRRRRR/tRtRtR	 R
 lt	R R lt
R R ltR R ltR R ltR R ltR R ltR R ltR# )a¹  Gemini long decode: one response spread over several generateContent hops.

Gemini 4 caps each request (32,768 tokens unary, 65,536 streamed) but lets ``maxOutputTokens`` reach
1,048,576 minus the input. A hop that hits the per-request cap with budget left ends with
``finishReason: CONTINUATION`` plus a ``continuationToken``; the client resends the SAME request with
that token (never the partial output) until any other finish reason. Each hop re-reads the prompt plus
everything generated so far, so per-hop ``promptTokenCount`` grows: usage is summed for billing (what
the google-genai SDK reports and Google bills) while the first hop's prompt is kept as the context size,
because compaction fed the summed prompt would fire far too early. A dropped stream resumes from its
last checkpoint token rather than restarting (Google bills a dropped stream up to that checkpoint).
Docs: https://ai.google.dev/gemini-api/docs/generate-content/long-decode
)Úannotations)ÚAnyÚOptionalÚxhighi   Úmaxi   Úultrai €  c               ó$   € V ^8„  d   QhRRRRRR/# )é   ÚmodelÚstrÚreasoning_configr   ÚreturnzOptional[int]© )Úformats   "Ú=/home/ubuntu/.hermes/hermes-agent/agent/gemini_long_decode.pyÚ__annotate__r      s&   € ÷ _ñ _¨ð _Àð _Èñ _ó    c                óž  € T ;'       g    RP                  4       P                  4       P                  R4      pVP                  R4      '       d,   \	        V\
        4      '       d   VP                  R4      RJ d   R# \        P                  \        VP                  R4      ;'       g    R4      P                  4       P                  4       4      # )z`Total output budget a Gemini 4 request gets for its reasoning effort, or None (per-request cap).Ú zgoogle/zgemini-4ÚenabledFNÚeffort)	ÚstripÚlowerÚremoveprefixÚ
startswithÚ
isinstanceÚdictÚgetÚ_LONG_DECODE_BUDGETSr   )r
   r   Únames   && r   Úlong_decode_max_output_tokensr       sš   € à�KˆK�R×ÑÓ ×&Ñ&Ó(×5Ñ5°iÓ@€DØ�?‰?˜:×&Ò&¬jÐ9IÌ4×.PÒ.PÐTd×ThÑThÐirÓTsÐw|ÓT|ÙÜ×#Ñ#¤CÐ(8×(<Ñ(<¸XÓ(F×(LÐ(LÈ"Ó$M×$SÑ$SÓ$U×$[Ñ$[Ó$]Ó^Ð^r   c               ó    € V ^8„  d   QhRRRR/# )r	   Úmax_output_tokensr   r   Úintr   )r   s   "r   r   r   %   s   € ÷ -ñ -¨ð -°ñ -r   c                ó”   € \        V \        4      '       d   \        V \        4      '       g   T M^ p\        ^V) \        ,          ) 4      # )zøMost hops a request with this total budget can take; 1 when it fits one request. The stale
watchdog scales by it (one timer spans every unary hop) and the hop loops stop one past it, so a
server that keeps answering CONTINUATION can't bill forever.)r   r#   Úboolr   Ú_HOP_TOKENS)r"   Úbudgets   & r   Úlong_decode_hopsr(   %   s?   € ô #-Ð->Ä×"DÒ"DÌZÐXiÔko×MpÒMpÑÐvw€FÜˆq�V�Gœ{Õ*Ð+Ó,Ð,r   c               ó    € V ^8„  d   QhRRRR/# )r	   Úapi_payloadr   r   r#   r   )r   s   "r   r   r   -   s   € ÷ ^ñ ^¨cð ^°cñ ^r   c                ó¸   € \        V \        4      '       d   V P                  R4      MRp\        V\        4      '       d   \        VP                  R4      4      # ^# )a  Non-streaming stale budgets are one timer around every unary hop of a long decode: scale it by
the hop count so a healthy multi-hop answer isn't killed and re-billed from hop 1. The run-budget
cap still applies afterwards; streaming re-arms on every chunk and needs no scaling.Ú
extra_bodyNr"   )r   r   r   r(   )r*   Úextras   & r   Úlong_decode_stale_multiplierr.   -   sJ   € ô .8¸ÄT×-JÒ-JˆK�O‰O˜LÔ)ÐPT€EÜ?IÈ%ÔQU×?VÒ?VÔ˜EŸI™IÐ&9Ó:Ó;Ð]Ð\]Ð]r   c               ó    € V ^8„  d   QhRRRR/# )r	   Úpayloadúdict[str, Any]r   r   )r   s   "r   r   r   5   s   € ÷ 4ñ 4˜ð 4¨>ñ 4r   c                óÚ   € \        V \        4      '       d   V P                  R 4      MRp\        V\        4      '       d   V'       d
   V^ ,          MRp\        V\        4      '       d   V# / # )Ú
candidatesN)r   r   r   Úlist)r0   r3   Úfirsts   &  r   Ú
_candidater6   5   sN   € Ü.8¸Ä$×.GÒ.G�—‘˜\Ô*ÈT€JÜ'¨
´D×9Ò9¿jˆJ�qŽMÈd€EÜ˜u¤d×+Ò+ˆ5Ð3°Ð3r   c               ó    € V ^8„  d   QhRRRR/# )r	   r0   r1   r   zOptional[str]r   )r   s   "r   r   r   ;   s   € ÷ Añ A ð A°=ñ Ar   c                óì   € \        V 4      pVP                  R4      p\        VP                  R4      ;'       g    R4      P                  4       R8X  d!   \	        V\        4      '       d   V'       d   V# R# )zWThe token to resend with when this hop ended on CONTINUATION; None on any other finish.ÚcontinuationTokenÚfinishReasonr   ÚCONTINUATIONN)r6   r   r   Úupperr   )r0   ÚcandÚtokens   &  r   Úcontinuation_tokenr?   ;   si   € ä�gÓ€DØ�H‰HÐ(Ó)€EÜ˜Ÿ™ Ó0×6Ð6°BÓ7×=Ñ=Ó?À>ÔQÔV`ÐafÔhk×VlÒVl×qvˆ5ð  Að  }Að  Ar   c               ó    € V ^8„  d   QhRRRR/# ©r	   Úhopsúlist[dict[str, Any]]r   r1   r   )r   s   "r   r   r   B   s   € ÷ ñ Ð.ð °>ñ r   c                ó¬  a€ \          Uau/ uF[  o\        ;QJ d    V3R lV  4       F  '       g   K   RM	  RM! V3R lV  4       4      '       g   KE  S\        V3R lV  4       4      bK]  	  ppV '       d
   V ^ ,          M/ p\        VP	                  R4      ;'       g    ^ 4      VR&   \        VP	                  R4      ;'       g    ^ 4      VR&   V# u upi )	zcSum every count across hops; ``initialPromptTokenCount`` (the google-genai name) is hop 1's prompt.c              3  ó.   <"  € T F
  pSV9   x € K  	  R # 5i)Nr   ©Ú.0ÚhÚkeys   & €r   Ú	<genexpr>Ú"merge_hop_usage.<locals>.<genexpr>D   s   øé € Ð^vÑquÐlmÐ_bÐfgÖ_gÓquùs   ƒTFc              3  ól   <"  € T F)  p\        VP                  S4      ;'       g    ^ 4      x € K+  	  R# 5i)é    N)r#   r   rF   s   & €r   rJ   rK   D   s'   øé € Ð:±T°”s˜1Ÿ5™5 ›:Ÿ?˜?¨×+Ð+³Tùs   ƒ!4¥4ÚpromptTokenCountÚinitialPromptTokenCountÚcachedContentTokenCountÚinitialCachedContentTokenCount)Ú_USAGE_COUNT_KEYSÚanyÚsumr#   r   )rB   rI   Úmergedr5   s   &`  r   Úmerge_hop_usagerV   B   s­   ø€ åFWÔwÑFW¸s×[^Ó[^Ô^vÑquÓ^v×[^×[^Ò[^Ô^vÑquÓ^v×[vÔ:ˆc”3Ô:±TÓ:Ó:Ò:ÑFW€FÐwßˆD�ŽG €EÜ(+¨E¯I©IÐ6HÓ,I×,NÐ,NÈQÓ(O€FÐ$Ñ%Ü/2°5·9±9Ð=VÓ3W×3\Ð3\Ð[\Ó/]€FÐ+Ñ,Ø€Mùò	 xs   ‹C›C²CÁCc               ó    € V ^8„  d   QhRRRR/# rA   r   )r   s   "r   r   r   K   s   € ÷ Kñ KÐ2ð K°~ñ Kr   c                óÄ  € V  UUu. uFH  p\        V4      P                  R4      ;'       g    / P                  R4      ;'       g    .  F  q"NK  	  KJ  	  ppp\        V R,          4      p/ VCR/ VP                  R4      ;'       g    / CRRRV/C/Cp\        V  Uu. uF  qP                  R4      ;'       g    / NK  	  up4      p/ V R,          CRV.RV/C# u uppi u upi )zbOne generateContent response whose model turn joins every hop's parts, ending as the last hop did.ÚcontentÚpartsÚroler
   ÚusageMetadatar3   éÿÿÿÿ)r6   r   rV   )rB   ÚhopÚpartrZ   ÚlastÚ	candidateÚusages   &      r   Úmerge_hop_responsesrc   K   så   € á!Ôj™T�c´
¸3³×0CÑ0CÀIÓ0N×0TÐ0TÐRT×/YÑ/YÐZaÓ/b×/hÐ/hÐfhÒ/h dŠTÑ/h‰T™T€EÑjÜ�d˜2•hÓ€DØe�4Ðe˜Ð$d¨¯©°Ó(;×(AÐ(A¸rÐ$dÀFÈGÐU\Ð^cÑ$dÑe€IÜÁtÓLÁtÀŸW™W _Ó5×;Ð;¸Ò;ÁtÑLÓM€EØJˆd�2�hÐJ˜ y k°?ÀEÑJÐJùó	 kùò Ms   †%C¬CÁCÂCÂ7Cc               ó$   € V ^8„  d   QhRRRRRR/# )r	   Úeventr1   Ú	hop_usagerC   r   z$tuple[dict[str, Any], Optional[str]]r   )r   s   "r   r   r   T   s(   € ÷ Uñ U ^ð UÐ@Tð UÐY}ñ Ur   c                óÂ  € \        V 4      pV'       d™   TP                  V P                  R4      ;'       g    / 4       \        V 4      P	                  4        UUu/ uF  w  r4VR9  g   K  W4bK  	  pppV P	                  4        UUu/ uF  w  r4VR8w  g   K  W4bK  	  uppRV./,          V3# \        V 4      pV'       dH   VP                  R4      '       d1   / V CR\        . VOV P                  R4      ;'       g    / N4      /CR3# VP                  R4      '       d   RMVP                  R4      pT \        V\        4      '       d   V'       d   V3# R3# u uppi u uppi )a6  ``(event to translate, token to resend with if the stream ends here)`` for one SSE event.

A CONTINUATION finish is not the end: its finish reason and (per-stream cumulative) usage are
held back in ``hop_usage`` and the token returned for the next hop. The real final event gets
the usage summed over every hop. A token on an event with no finish is a mid-stream checkpoint
(every ~5K tokens past 32K): it commits that event and everything before it, so the caller resumes
a dropped stream by resending the request with it; a drop with no clean checkpoint restarts.
r\   r:   r9   r3   N)r:   r9   )r?   Úappendr   r6   ÚitemsrV   r   r   )re   rf   r>   ÚkÚvr=   Ú
checkpoints   &&     r   Úsplit_stream_continuationrm   T   s>  € ô ˜uÓ%€EßØ×Ñ˜Ÿ™ ?Ó3×9Ð9°rÔ:Ü!+¨EÓ!2×!8Ñ!8Ô!:ÔmÑ!:™˜¸aÐGlÑ>l”�’Ñ!:ˆÑmØ!&§¡¤ÔG¡™˜°!°Ñ2F”�’¡ÒGÈ<ÐZ^ÐY_ÐJ`Õ`ÐbgÐgÐgÜ�eÓ€Dß�T—X‘X˜n×-Ò-Øj�%Ðj˜¬/Ð:h¸IÐ:hÀuÇyÁyÐQ`ÓGa×GgÐGgÐegÐ:hÓ*iÑjÐlpÐpÐpØŸ™ .×1Ò1‘°t·x±xÐ@SÓ7T€JØ¤
¨:´s× ;Ò ;Ç
�*ÐTÐTÐPTÐTÐTùó nùÛGs   ÁEÁ*EÂEÂEN)rN   rP   ÚcandidatesTokenCountÚthoughtsTokenCountÚtoolUsePromptTokenCountÚtotalTokenCount)Ú__doc__Ú
__future__r   Útypingr   r   r   r&   rR   r    r(   r.   r6   r?   rV   rc   rm   r   r   r   Ú<module>ru      sa   ðñõ #ç  ð   ¨%°¸GÀYÐOÐ à€ðÐ õ_õ-õ^õ4õAõõK÷Ur   