
    piZ#                        d Z ddlmZ ddlZddlZddlmZ ddlmZ ddl	m
Z
mZ erddlmZ  ej        e          ZdZd	Zd
ZdZdZddZ G d d          ZdS )zIntelligent context compression for multi-agent meetings.

Prevents whiteboard explosion by compressing scratchpad content
while preserving recent entries in full and keeping full transcripts.
    )annotationsN)TYPE_CHECKING)format_scratchpad_summary)MeetingStateScratchpadEntry)	LLMClienti        zSummarize the following meeting discussion into a structured briefing.
Preserve: key arguments, disagreements, decisions, open questions.
Remove: rhetorical flourishes, examples used for illustration, repetition.
Output in bullet points, max 800 tokens.zSummarize the following background material into a structured briefing.
Preserve: key facts, requirements, constraints, goals.
Remove: verbose explanations, examples, repetition.
Output in bullet points, max 1500 tokens.textstrreturnintc                    | sdS t          t          j        d|                     }t          |           |z
  }|dz  }|dz  }t          ||z             S )a  Estimate token count for mixed Chinese/English text.

    Uses a heuristic: Chinese characters ~1.5 chars/token,
    English/ASCII ~4 chars/token. No external dependencies.

    Args:
        text: Input text to estimate.

    Returns:
        Approximate token count.
    r   z[\u4e00-\u9fff\u3400-\u4dbf]g      ?g      @)lenrefindallr   )r   chinese_charsother_charschinese_tokensother_tokenss        :/root/projects/multi-agents-meeting/src/context_manager.pyestimate_tokensr   )   sb      q
#BDIIJJMd))m+K"S(N$L~,---    c                  <    e Zd ZdZdddZddZddZddZddZdS )ContextManagera]  Manage meeting context to prevent whiteboard explosion.

    Uses a three-level compression strategy:
    - Level 0: Full content (under budget)
    - Level 1: Truncate early entries, keep recent in full
    - Level 2: LLM-summarize early entries, keep recent in full

    Args:
        budget_tokens: Maximum tokens for the scratchpad portion.
    p  budget_tokensr   r   Nonec                    || _         d S )N)r   )selfr   s     r   __init__zContextManager.__init__M   s    *r   entrieslist[ScratchpadEntry]clientr   r   c                l   |sdS t          |          }t          |          }|| j        k    rt                              d|           |S t          |          t          k    r6t          |          dk    r t          dt          |          dz
            nd}nt          }|dk    r|d|          n|}|dk    r|| d         ng }|rt          |          nd}t          |          }	t          d| j        |	z
            }
g }|D ]S}|j	        }t          |          t          k    r|dt                   dz   }|                    d|j         d	|            Td
                    |          }t          |          }||
k    r4|
dk    r.|r,t                              d||	z              |}|r|d
|z   z  }|S t                              d           |r0t          |          }|                    t          d|dg          }n%|                    t          d|dg          }d| S |rd| d| S d| S )u  Compress scratchpad entries to fit within budget.

        Strategy (progressive disclosure):
        1. If raw scratchpad < budget → return full text (Level 0)
        2. If exceeds → truncate early entries, keep recent 2 full (Level 1)
        3. If still exceeds → LLM-summarize early entries (Level 2)

        Args:
            entries: All scratchpad entries.
            client: LLM client for Level 2 summarization.

        Returns:
            Compressed scratchpad text fitting within budget.
        zNo discussion yet.z$Level 0: scratchpad fits (%d tokens)   r   N z...[z]: 
z,Level 1: truncated early entries (%d tokens)zLevel 2: LLM summarizationuserrolecontentsystemmessagesz[Discussion Summary]
z[Earlier Discussion Summary]
z

[Recent Entries]
)r   r   r   loggerdebugr   _RECENT_ENTRIES_TO_KEEPminmaxr-   _TRUNCATE_CHARSappend
agent_namejoinchat_SUMMARIZE_SCRATCHPAD_PROMPT)r    r"   r$   	full_textfull_tokensrecent_countearly_entriesrecent_entriesrecent_textrecent_tokensearly_budgettruncated_linesentryr-   truncated_texttruncated_tokenscombinedearly_full_textsummarys                      r   compact_scratchpadz!ContextManager.compact_scratchpadP   s   &  	(''-g66	%i00 $,,,LL?MMM
 w<<2227:7||a7G7G3q#g,,"2333QLL2L3?!3C3C,//4@14D4D,00"CQY/???WY'44 1d0=@AA &(" 	G 	GEmG7||o--!"2?"23e;""#Eu'7#E#EG#E#EFFFF?33*>::|++q0@0@_0@LLGIY\iIijjj%H /D;..O 	1222 	67FFOkk3#)oFFG "  GG kk3#)i@@A "  G 6G555 	a`G``S^```1111r   stater   c                f   d|j          dg}|j        rO|j        dk    s|j        s|                    d|j         d           n|                    d|j         d           |                     |j        |          }|                    d|j         d|            d                    |          S )aR  Build compressed context for the PM agent.

        Round 0 (first round): includes full context.
        Later rounds: uses context_summary if available.

        Args:
            state: Current meeting state.
            client: LLM client for compression.

        Returns:
            Formatted string for PM's user message.
        z## Meeting Topic

r)   r   z## Background Context

z!## Background Context (Summary)

z## Current Whiteboard (Round z)

)topiccontextcurrent_roundcontext_summaryr7   rK   
scratchpadr9   )r    rL   r$   partsscratchpad_texts        r   build_pm_contextzContextManager.build_pm_context   s    " C5;BBBC = 	^"a''u/D'JJJJKKKK\5CX\\\]]] 11%2BFKK`U5H````aaayyr   target_agent	pm_promptc                Z   g }|j         r|                    d|j          d           n%|j        r|                    d|j         d           |                     |j        |          }|                    |           |r|                    d|            d                    |          S )a  Build compressed context for a specific agent.

        Agents get context_summary (not full context) and compressed scratchpad.

        Args:
            state: Current meeting state.
            target_agent: Name of the agent receiving this context.
            pm_prompt: The PM's specific question for this agent.
            client: LLM client for compression.

        Returns:
            Formatted string for the agent's scratchpad_summary parameter.
        z[Background]
r)   z
[PM's Question]
)rQ   r7   rO   rK   rR   r9   )r    rL   rV   rW   r$   rS   rT   s          r   build_agent_contextz"ContextManager.build_agent_context   s    (    	=LLC%*?CCCDDDD] 	=LL;%-;;;<<< 11%2BFKK_%%%  	<LL:y::;;;yyr   rO   c                    |sdS t          |          }|t          k    r|S |                    t          d|dg          }|S )a/  Generate a summary of long background context.

        If context is short enough, returns it as-is.

        Args:
            context: Original background context.
            client: LLM client for summarization.

        Returns:
            Original context if short, LLM summary if long.
        r'   r*   r+   r.   )r   _CONTEXT_SUMMARY_THRESHOLDr:   _SUMMARIZE_CONTEXT_PROMPT)r    rO   r$   tokensrJ   s        r   summarize_contextz ContextManager.summarize_context   s_       	2 ))///N++,%'::;  
 
 r   N)r   )r   r   r   r   )r"   r#   r$   r   r   r   )rL   r   r$   r   r   r   )
rL   r   rV   r   rW   r   r$   r   r   r   )rO   r   r$   r   r   r   )	__name__
__module____qualname____doc__r!   rK   rU   rY   r^    r   r   r   r   A   s        	 	+ + + + +S2 S2 S2 S2j       @$  $  $  $ L     r   r   )r   r   r   r   )rb   
__future__r   loggingr   typingr   	src.agentr   
src.modelsr   r   src.llm_clientr   	getLoggerr_   r1   r[   r3   r6   r;   r\   r   r   rc   r   r   <module>rk      s    # " " " " "  				             / / / / / / 4 4 4 4 4 4 4 4 )((((((		8	$	$ "  / 0 . . . .0E E E E E E E E E Er   