
    `gj[                         d Z ddlZddlmZmZmZ ddedededdfdZdededefd	Z	d
e
dee
e
f   fdZ	 	 ddeee
ef      de
dedeee
ef      fdZy)uB  Anthropic prompt caching strategy.

Single layout: ``system_and_3``. 4 cache_control breakpoints — system
prompt + last 3 non-system messages, all at the same TTL (5m or 1h).
Reduces input token costs by ~75% on multi-turn conversations within a
single session.

Pure functions -- no class state, no AIAgent dependency.
    N)AnyDictListmsgcache_markernative_anthropicreturnc                 2   | j                  dd      }| j                  d      }|dk(  r|r|| d<   y||dk(  r|dk(  r|sy|dk(  r|sy|| d<   yt        |t              rd||d	g| d<   yt        |t              r|r|d
   }t        |t              r||d<   yyyy)zFAdd cache_control to a single message, handling all format variations.role contenttoolcache_controlN	assistanttext)typer   r   )get
isinstancestrlistdict)r   r   r   r   r   lasts         G/root/.hermes/venv/lib/python3.12/site-packages/agent/prompt_caching.py_apply_cache_markerr      s    7762Dggi Gv~*  ,O'R-6>"2
 ;'7 +O'3W|L
I 	'4 Wr{dD!$0D! " &-     c                     |ry| j                  d      }||dk(  ryt        |t              r t        |      xr t        |d   t              S t        |t
              S )u  True if a marker on this message is actually honored by the provider.

    On the native Anthropic layout every message works (top-level markers are
    relocated by the adapter). On the envelope layout (OpenRouter et al.) only
    markers inside content parts are honored: empty-content messages (e.g.
    assistant turns that are pure tool_calls) and empty tool messages would
    receive a top-level marker the provider ignores — wasting one of the four
    breakpoints. Skip those so the breakpoints land on messages that count.
    Tr   r   Fr   )r   r   r   boolr   r   )r   r   r   s      r   _can_carry_markerr   4   sY     ggi G'R-'4 
 G}>GBK!>>gs##r   ttlc                 "    ddi}| dk(  rd|d<   |S )zCBuild a cache_control marker dict for the given TTL ('5m' or '1h').r   	ephemeral1hr     )r    markers     r   _build_markerr&   L   s!    $k2F
d{uMr   api_messages	cache_ttlc                    t        j                  |       }|s|S t        |      }d}|d   j                  d      dk(  rt	        |d   ||       |dz  }d|z
  }t        t        |            D cg c]+  }||   j                  d      dk7  rt        ||   |      r|- }}|| d D ]  }	t	        ||	   ||        |S c c}w )a  Apply system_and_3 caching strategy to messages for Anthropic models.

    Places up to 4 cache_control breakpoints: system prompt + last 3 non-system
    messages, all at the same TTL.

    Returns:
        Deep copy of messages with cache_control breakpoints injected.
    r   r   system)r         N)copydeepcopyr&   r   r   rangelenr   )
r'   r(   r   messagesr%   breakpoints_used	remaininginon_sysidxs
             r   apply_anthropic_cache_controlr7   T   s     }}\*H9%F{v(*HQKBRSA$$I s8}%A;??6"h.hqk<LM 	
G  	z{# VHSM6DTUV Os   /0B?)F)5mF)__doc__r-   typingr   r   r   r   r   r   r   r   r&   r7   r$   r   r   <module>r;      s     " ""1T "1 "1 "1Z^ "1J$4 $4 $D $0s tCH~  "#tCH~&## # 
$sCx.	#r   