
    =i*                        S r SSKJr  SSKJrJrJr  SSKJrJ	r	J
r
Jr  SSKJrJrJrJrJrJrJrJrJrJr  SSKJrJrJr  \(       a  SSKJr  SSKJr   " S	 S
\5      r/ SQr g)z1PII detection and handling middleware for agents.    )annotations)TYPE_CHECKINGAnyLiteral)	AIMessage
AnyMessageHumanMessageToolMessage)
PIIDetectionErrorPIIMatchRedactionRuleResolvedRedactionRuleapply_strategydetect_credit_carddetect_email	detect_ipdetect_mac_address
detect_url)AgentMiddleware
AgentStatehook_config)Callable)Runtimec                     ^  \ rS rSrSrSSSSSS.             SU 4S jjjr\SS	 j5       rSS
 jr\	" S/S9      SS j5       r
      SS jrSrU =r$ )PIIMiddleware   az  Detect and handle Personally Identifiable Information (PII) in agent conversations.

This middleware detects common PII types and applies configurable strategies
to handle them. It can detect emails, credit cards, IP addresses,
MAC addresses, and URLs in both user input and agent output.

Built-in PII types:
    - `email`: Email addresses
    - `credit_card`: Credit card numbers (validated with Luhn algorithm)
    - `ip`: IP addresses (validated with stdlib)
    - `mac_address`: MAC addresses
    - `url`: URLs (both `http`/`https` and bare URLs)

Strategies:
    - `block`: Raise an exception when PII is detected
    - `redact`: Replace PII with `[REDACTED_TYPE]` placeholders
    - `mask`: Partially mask PII (e.g., `****-****-****-1234` for credit card)
    - `hash`: Replace PII with deterministic hash (e.g., `<email_hash:a1b2c3d4>`)

Strategy Selection Guide:

| Strategy | Preserves Identity? | Best For                                |
| -------- | ------------------- | --------------------------------------- |
| `block`  | N/A                 | Avoid PII completely                    |
| `redact` | No                  | General compliance, log sanitization    |
| `mask`   | No                  | Human readability, customer service UIs |
| `hash`   | Yes (pseudonymous)  | Analytics, debugging                    |

Example:
    ```python
    from langchain.agents.middleware import PIIMiddleware
    from langchain.agents import create_agent

    # Redact all emails in user input
    agent = create_agent(
        "openai:gpt-5",
        middleware=[
            PIIMiddleware("email", strategy="redact"),
        ],
    )

    # Use different strategies for different PII types
    agent = create_agent(
        "openai:gpt-4o",
        middleware=[
            PIIMiddleware("credit_card", strategy="mask"),
            PIIMiddleware("url", strategy="redact"),
            PIIMiddleware("ip", strategy="hash"),
        ],
    )

    # Custom PII type with regex
    agent = create_agent(
        "openai:gpt-5",
        middleware=[
            PIIMiddleware("api_key", detector=r"sk-[a-zA-Z0-9]{32}", strategy="block"),
        ],
    )
    ```
redactNTF)strategydetectorapply_to_inputapply_to_outputapply_to_tool_resultsc               $  > [         TU ]  5         X@l        XPl        X`l        [        UUUS9R                  5       U l        U R                  R                  U l        U R                  R                  U l	        U R                  R                  U l
        g)aL  Initialize the PII detection middleware.

Args:
    pii_type: Type of PII to detect. Can be a built-in type
        (`email`, `credit_card`, `ip`, `mac_address`, `url`)
        or a custom type name.
    strategy: How to handle detected PII:

        * `block`: Raise PIIDetectionError when PII is detected
        * `redact`: Replace with `[REDACTED_TYPE]` placeholders
        * `mask`: Partially mask PII (show last few characters)
        * `hash`: Replace with deterministic hash (format: `<type_hash:digest>`)

    detector: Custom detector function or regex pattern.

        * If `Callable`: Function that takes content string and returns
            list of PIIMatch objects
        * If `str`: Regex pattern to match PII
        * If `None`: Uses built-in detector for the pii_type

    apply_to_input: Whether to check user messages before model call.
    apply_to_output: Whether to check AI messages after model call.
    apply_to_tool_results: Whether to check tool result messages after tool execution.

Raises:
    ValueError: If pii_type is not built-in and no detector is provided.
)pii_typer   r   N)super__init__r    r!   r"   r   resolve_resolved_ruler$   r   r   )selfr$   r   r   r    r!   r"   	__class__s          o/home/dmtnaga/Documents/work/airagagent/rag_env/lib/python3.13/site-packages/langchain/agents/middleware/pii.pyr&   PIIMiddleware.__init__[   s    J 	,.%:"5B6
 ')	 	
 ++44++44++44    c                N    U R                   R                   SU R                   S3$ )zName of the middleware.[])r*   __name__r$   )r)   s    r+   namePIIMiddleware.name   s&     ..))*!DMM?!<<r-   c                l    U R                  U5      nU(       d  U/ 4$ [        XU R                  5      nX24$ )z<Apply the configured redaction rule to the provided content.)r   r   r   )r)   contentmatches	sanitizeds       r+   _process_contentPIIMiddleware._process_content   s6    --(B;"7T]]C	!!r-   end)can_jump_toc                   U R                   (       d  U R                  (       d  gUS   nU(       d  g[        U5      nSnU R                   (       a  SnSn[        [	        U5      S-
  SS5       H"  n[        X8   [        5      (       d  M  X8   nUn  O   Ubl  U(       ae  UR                  (       aT  [        UR                  5      n	U R                  U	5      u  pU(       a%  [        U
UR                  UR                  S9nXU'   SnU R                  (       a  Sn[        [	        U5      S-
  SS5       H  n[        X8   [        5      (       d  M  Un  O   Ub  [        US-   [	        U5      5       H  nX8   n[        U[        5      (       d  M  UnUR                  (       d  M3  [        UR                  5      n	U R                  U	5      u  pU(       d  Md  [        U
UR                  UR                  UR                  S9nXU'   SnM     U(       a  SU0$ g)	aA  Check user messages and tool results for PII before model invocation.

Args:
    state: The current agent state.
    runtime: The langgraph runtime.

Returns:
    Updated state with PII handled according to strategy, or None if no PII detected.

Raises:
    PIIDetectionError: If PII is detected and strategy is "block".
NmessagesF   )r5   idr2   T)r5   r@   r2   tool_call_id)r    r"   listrangelen
isinstancer	   r5   strr8   r@   r2   r   r
   rA   )r)   stateruntimer=   new_messagesany_modifiedlast_user_msglast_user_idxir5   new_contentr6   updated_messagelast_ai_idxmsgtool_msgs                   r+   before_modelPIIMiddleware.before_model   s   $ ""4+E+E$H~  M M3x=1,b"5hk<88$,KM$%M	 6 (]}?T?Tm334'+'<'<W'E$2> +(++*//3O 3B/#'L %%K3x=1,b"5hk955"#K 6
 &{QH>A"+C!#{33#&'//$"%h&6&6"7/3/D/DW/M,&$ +6$/'{{!))1)>)>	+ +:Q'+- ?0 --r-   c                   U R                   (       d  gUS   nU(       d  gSnSn[        [        U5      S-
  SS5       H"  nX6   n[        U[        5      (       d  M  UnUn  O   Ub  U(       a  UR
                  (       d  g[        UR
                  5      nU R                  U5      u  pU
(       d  g[	        U	UR                  UR                  UR                  S9n[        U5      nXU'   SU0$ )a-  Check AI messages for PII after model invocation.

Args:
    state: The current agent state.
    runtime: The langgraph runtime.

Returns:
    Updated state with PII handled according to strategy, or None if no PII detected.

Raises:
    PIIDetectionError: If PII is detected and strategy is "block".
Nr=   r>   r?   )r5   r@   r2   
tool_calls)r!   rC   rD   rE   r   r5   rF   r8   r@   r2   rV   rB   )r)   rG   rH   r=   last_ai_msgrP   rM   rQ   r5   rN   r6   rO   rI   s                r+   after_modelPIIMiddleware.after_model   s    " ##$ s8}q("b1A+C#y))! 2 k9L9L k))*#44W= $~~!!"--	
 H~$3[!L))r-   )r(   r    r!   r"   r   r$   r   )r$   zALiteral['email', 'credit_card', 'ip', 'mac_address', 'url'] | strr   z*Literal['block', 'redact', 'mask', 'hash']r   z,Callable[[str], list[PIIMatch]] | str | Noner    boolr!   rZ   r"   rZ   returnNone)r[   rF   )r5   rF   r[   ztuple[str, list[PIIMatch]])rG   r   rH   r   r[   zdict[str, Any] | None)r1   
__module____qualname____firstlineno____doc__r&   propertyr2   r8   r   rS   rX   __static_attributes____classcell__)r*   s   @r+   r   r      s    ;B @HAE# %&+25S25 =	25
 ?25 25 25  $25 
25 25h = =" eW%[[ [ 
	[ &[z8*8* 8* 
	8* 8*r-   r   )r   r   r   r   r   r   r   N)!r`   
__future__r   typingr   r   r   langchain_core.messagesr   r   r	   r
   &langchain.agents.middleware._redactionr   r   r   r   r   r   r   r   r   r   !langchain.agents.middleware.typesr   r   r   collections.abcr   langgraph.runtimer   r   __all__ r-   r+   <module>rm      sN    7 " . . T T   W V()U*O U*pr-   