
    $j]                     l   d Z ddlZddlmZ ddlZ ej        d          ZdZdZdZ	de
eeef                  d	e
e         fd
Zde
eeef                  d	efdZde
eeef                  d	efdZ	 	 	 	 d)deeef         dedz  de
eeef                  dz  dededz  d	efdZ	 d*dede
e         dededz  d	ef
dZ	 	 d+dede
e         dededz  ded	efdZdZd*dedz  d	efdZ e            ZdZddded ed!e
eeef                  d"ed#edz  d	efd$Zd%Zd&ed'ed!e
eeef                  d"ed	ef
d(ZdS ),a  
System prompts for the reflect agent.

The reflect agent uses hierarchical retrieval:
1. search_mental_models - User-curated summaries (highest quality)
2. search_observations - Consolidated knowledge with freshness awareness
3. recall - Raw facts as ground truth fallback
    N)Anycl100k_baseg?zWYou are a reflection agent that answers questions by reasoning over retrieved memories.zPYou are a thoughtful assistant that synthesizes answers from retrieved memories.
directivesreturnc                     g }| D ]O}|                     dd          }|                     dd          }|r|                    |rd| d| n|           P|S )z-Extract directive rules as a list of strings.name contentz**z**: )getappend)r   rules	directiver   r
   s        l/home/rurouni/.hermes/hermes-agent/venv/lib/python3.11/site-packages/hindsight_api/engine/reflect/prompts.py_extract_directive_rulesr      sz    E H H	}}VR((--	2.. 	HLLTF1d11111wGGGL    c                     | sdS t          |           }|sdS g d}|D ]}|                    d|            |                    g d           d                    |          S )zBuild the directives section for the system prompt.

    Directives are hard rules that MUST be followed in all responses.
    r	   )z## DIRECTIVES (MANDATORY)z6These are hard rules you MUST follow in ALL responses:r	   z- )r	   zINEVER violate these directives, even if other context suggests otherwise.zjIMPORTANT: Do NOT explain or justify how you handled directives in your answer. Just follow them silently.r	   
)r   r   extendjoin)r   r   partsrules       r   build_directives_sectionr   $   s    
  r$Z00E r  E  " "[$[[!!!!	LL	
 	
 	
   99Ur   c                 @   | sdS t          |           }|sdS g d}t          |d          D ]\  }}|                    | d|             |                    d           |                    d           |                    d           d                    |          S )z
    Build a reminder section for directives to place at the end of the prompt.

    Args:
        directives: List of directive mental models with observations
    r	   )r	   z!## REMINDER: MANDATORY DIRECTIVESzLBefore responding, ensure your answer complies with ALL of these directives:r	      z. zBYour response will be REJECTED if it violates any directive above.zRDo NOT include any commentary about how you handled directives - just follow them.r   )r   	enumerater   r   )r   r   r   ir   s        r   build_directives_reminderr   D   s      r$Z00E r  E UA&& % %4^^T^^$$$$	LL	LLUVVV	LLefff99Ur   Fbank_profilecontexthas_mental_modelsbudgetc                     |                      dd          }|                      dd          }g }|                    ddg           |r"|                    t          |                     |                    |r|                                nt
          dddg           |                    g d           |r|                    g d           n|                    g d	           |                    g d
           |rm|                                }|dk    r|                    g d           n;|dk    r|                    g d           n|dk    r|                    g d           |                    d           |r|                    g d           n|                    g d           |                    g d           |                    d           |                    d|            |r|                    d|            |                      di           }	|	rg }
d|	v r|
                    d|	d                     d|	v r|
                    d|	d                     d|	v r|
                    d|	d                     |
r+|                    dd                    |
                      |r|                    d |            |r"|                    t          |                     d!                    |          S )"a  
    Build the system prompt for tool-calling reflect agent.

    The agent uses hierarchical retrieval:
    1. search_mental_models - User-curated summaries (try first, if available)
    2. search_observations - Consolidated knowledge with freshness
    3. recall - Raw facts as ground truth

    Args:
        bank_profile: Bank profile with name and mission
        context: Optional additional context
        directives: Optional list of directive mental models to inject as hard rules
        has_mental_models: Whether the bank has any mental models (skip if not)
        budget: Search depth budget - "low", "mid", or "high". Controls exploration thoroughness.
    r   	Assistantmissionr	   zvCRITICAL: You MUST ONLY use information from retrieved tool results. NEVER make up names, people, events, or entities.z@Answer the user's question by reasoning over retrieved memories.)z7## LANGUAGE RULE (default - directives take precedence)z[- By default, detect the language of the user's question and respond in that SAME language.zY- If the question is in Chinese, respond in Chinese. If in Japanese, respond in Japanese.zM- IMPORTANT: The DIRECTIVES section above has HIGHER PRIORITY than this rule.z^  If a directive specifies a language (e.g. 'Always respond in French'), follow the directive.r	   z## CRITICAL RULESzL- ONLY use information from tool results - no external knowledge or guessingzF- You SHOULD synthesize, infer, and reason from the retrieved memoriesz:- You MUST search before saying you don't have informationr	   z## How to ReasonzS- If memories mention someone did an activity, you can infer they likely enjoyed itz7- Synthesize a coherent narrative from related memoriesz:- Be a thoughtful interpreter, not just a literal repeaterzP- When the exact answer isn't stated, use what IS stated to give the best answerr	   z"## HIERARCHICAL RETRIEVAL STRATEGYr	   )zEYou have access to THREE levels of knowledge. Use them in this order:r	   z7### 1. MENTAL MODELS (search_mental_models) - Try Firstz.- User-curated summaries about specific topicsz3- HIGHEST quality - manually created and maintainedzR- If a relevant mental model exists and is FRESH, it may fully answer the questionzB- Check `is_stale` field - if stale, also verify with lower levelsr	   z;### 2. OBSERVATIONS (search_observations) - Second Priority+- Auto-consolidated knowledge from memories@- Check `is_stale` field - if stale, ALSO use recall() to verify/- Good for understanding patterns and summariesr	   z(### 3. RAW FACTS (recall) - Ground Truth3- Individual memories (world facts and experiences)z\- Use when: no mental models/observations exist, they're stale, or you need specific detailsz{- MANDATORY: If search_mental_models and search_observations both return 0 results, you MUST call recall() before giving upz>- This is the source of truth that other levels are built fromr	   )zCYou have access to TWO levels of knowledge. Use them in this order:r	   z5### 1. OBSERVATIONS (search_observations) - Try Firstr%   r&   r'   r	   z(### 2. RAW FACTS (recall) - Ground Truthr(   zN- Use when: no observations exist, they're stale, or you need specific detailszi- MANDATORY: If search_observations returns 0 results or count=0, you MUST call recall() before giving upz>- This is the source of truth that observations are built fromr	   )z## Query Strategyzirecall() uses semantic search. NEVER just echo the user's question - decompose it into targeted searches:r	   up   BAD: User asks 'recurring lesson themes between students' → recall('recurring lesson themes between students')z,GOOD: Break it down into component searches:z9  1. recall('lessons') - find all lesson-related memoriesz7  2. recall('teaching sessions') - alternative phrasingz?  3. recall('student progress') - find student-related memoriesr	   zYThink: What ENTITIES and CONCEPTS does this question involve? Search for each separately.r	   low)z+## RESEARCH DEPTH: SHALLOW (Quick Response)z$- Prioritize speed over completenesszJ- If mental models or observations provide a reasonable answer, stop therezA- Only dig deeper if the initial results are clearly insufficientz8- Prefer a quick overview rather than exhaustive detailsz,- Answer promptly with available informationr	   mid)z&## RESEARCH DEPTH: MODERATE (Balanced)z&- Balance thoroughness with efficiencyz6- Check multiple sources when the question warrants itz1- Verify stale data if it's central to the answerz4- Don't over-explore, but ensure reasonable coverager	   high)z.## RESEARCH DEPTH: DEEP (Thorough Exploration)z*- Explore comprehensively before answeringz.- Search across all available knowledge levelsz2- Use multiple query variations to ensure coveragez6- Verify information across different retrieval levelsz8- Use expand() to get full context on important memoriesz<- Take time to synthesize a complete, well-researched answerr	   z## Workflow)zH1. First, try search_mental_models() - check if a curated summary existszY2. If no mental model or it's stale, try search_observations() for consolidated knowledgezU3. If observations are stale OR you need specific details, use recall() for raw factsz=4. Use expand() if you need more context on specific memoriesz>5. When ready, call done() with your answer and supporting IDs)zF1. First, try search_observations() - check for consolidated knowledgezk2. If search_observations returns 0 results OR observations are stale, you MUST call recall() for raw factsz=3. Use expand() if you need more context on specific memoriesz>4. When ready, call done() with your answer and supporting IDs)	r	   z0## Output Format: Well-Formatted Markdown Answerz:Call done() with a well-formatted markdown 'answer' field.za- USE markdown formatting for structure (headers, lists, bold, italic, code blocks, tables, etc.)zX- CRITICAL: Add blank lines before and after block elements (tables, code blocks, lists)zF- Format for clarity and readability with proper spacing and hierarchyzL- NEVER include memory IDs, UUIDs, or 'Memory references' in the answer textz[- Put IDs ONLY in the memory_ids/mental_model_ids/observation_ids arrays, not in the answerz- CRITICAL: This is a NON-CONVERSATIONAL system. NEVER ask follow-up questions, offer further assistance, or suggest next steps. Your answer must be complete and self-contained. The user cannot reply.z## Memory Bank: 	Mission: disposition
skepticismskepticism=
literalismliteralism=empathyempathy=Disposition: , 
## Additional Context
r   )	r   r   r   r   strip_DEFAULT_ROLElowerr   r   )r   r   r   r    r!   r   r$   r   budget_lowerr-   traitss              r   build_system_prompt_for_toolsr<   b   s(   , FK00Dy"--GE 
LL E	
    ;-j99:::	LL&9GMMOOOMN		
   
LL	
 	
 	
  2  )
  	
 	
 	
 	
0 	  	
 	
 	
$ 
LL	
 	
 	
  "  %||~~5  LL  
 
 
 
 U""LL  	 	 	 	 V##LL	 	 	   
LL 
  	
 	
 	
 	
 	  	
 	
 	
 
LL
	
 
	
 
	
   
LL	LL*D**+++ ,***+++ ""="55K 	>;&&MMCL(ACCDDD;&&MMCL(ACCDDD##MM=[%;==>>> 	>LL<6):):<<=== <:::;;;  <.z::;;;99Ur   querycontext_historyadditional_contextc           
      F   g }|                     dd          }|                     dd          }|                    d|            |r|                    d|            |                     di           }|rg }d|v r|                    d	|d                     d
|v r|                    d|d
                     d|v r|                    d|d                     |r+|                    dd                    |                      |r|                    d|            |r|                    d           t          |d          D ]y\  }	}
|
d         }|
d         }	 t	          j        |dt          d          }n&# t          t          f$ r t          |          }Y nw xY w|                    d|	 d| d| d           z|                    d|             |r|                    d           n|                    d           d                    |          S ) z,Build the user prompt for the reflect agent.r   r#   r$   r	   ## Memory Bank Context
Name: r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   z7
## Tool Results (synthesize and reason from this data)r   tooloutput   Findentdefaultensure_asciiz

### Call z: z	
```json

```
## Question
z
## Instructions
Based on the tool results above, either call more tools or provide your final answer. Synthesize and reason from the data - make reasonable inferences when helpful. If you have related information, use it to give the best possible answer.a  
## Instructions
Start by searching for relevant information using the hierarchical retrieval strategy:
1. Try search_mental_models() first for curated summaries
2. Try search_observations() for consolidated knowledge
3. Use recall() for specific details or to verify stale datar   )	r   r   r   r   jsondumpsstr	TypeError
ValueError)r=   r>   r   r?   r   r   r$   r-   r;   r   entryrB   rC   
output_strs                 r   build_agent_promptrR   O  s    E FK00Dy"--G	LL8$88999 ,***+++ ""="55K 	>;&&MMCL(ACCDDD;&&MMCL(ACCDDD##MM=[%;==>>> 	>LL<6):):<<===  GE1CEEFFF  
POPPP!/155 	P 	PHAu=D8_F)!Zq#TYZZZ

z* ) ) ) [[


)LLNqNNDNNZNNNOOOO 
LL*5**+++  
X	
 	
 	
 	
 	K	
 	
 	
 99Us   %F F&%F&順 max_context_tokensc                 X   g }|                     dd          }|                     dd          }|                    d|            |r|                    d|            |                     di           }|rg }	d|v r|	                    d	|d                     d
|v r|	                    d|d
                     d|v r|	                    d|d                     |	r+|                    dd                    |	                      |r|                    d|            |r*|                    d           t          |t          z            }
g }d}t          |          D ]}|d         }|d         }	 t          j        |dt          d          }n&# t          t          f$ r t          |          }Y nw xY wd| d| d}t          t                              |                    }||
k    rd} n|                    |           |
|z  }
t          |          D ]}|                    |           |r|                    d           n|                    d           |                    d|             |                    d           d                    |          S ) z?Build the final prompt when forcing a text response (no tools).r   r#   r$   r	   rA   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   z9
## Retrieved Data (synthesize and reason from this data)FrB   rC   rD   rE   z

### From z
:
```json
rI   TzR
*Note: Some earlier tool results were omitted to stay within the context window.*z)
## Retrieved Data
No data was retrieved.rJ   aJ  
## Instructions
Provide a thoughtful answer by synthesizing and reasoning from the retrieved data above. You can make reasonable inferences from the memories, but don't completely fabricate information. If the exact answer isn't stated, use what IS stated to give the best possible answer. Only say 'I don't have information' if the retrieved data is truly unrelated to the question.

IMPORTANT: Output ONLY the final answer. Do NOT include meta-commentary like "I'll search..." or "Let me analyze...". Do NOT explain your reasoning process. Just provide the direct synthesized answer.r   )r   r   r   int_FINAL_PROMPT_CONTEXT_FRACTIONreversedrK   rL   rM   rN   rO   len_TIKTOKEN_ENCODINGencode)r=   r>   r   r?   rT   r   r   r$   r-   r;   token_budgetrendered	truncatedrP   rB   rC   rQ   blockblock_tokenss                      r   build_final_promptra     s3    E FK00Dy"--G	LL8$88999 ,***+++ ""="55K 	>;&&MMCL(ACCDDD;&&MMCL(ACCDDD##MM=[%;==>>> 	>LL<6):):<<===  GE1CEEFFF  DQRRR-0NNOO 	o.. 	) 	)E=D8_F)!Zq#TYZZZ

z* ) ) ) [[


)E$EEJEEEE188??@@Ll** 	OOE"""L(LLh'' 	  	 ELL 	pLLnoooBCCC 
LL*5**+++ 
LL	6	 	 	 99Us   =F F>=F>a  CRITICAL: You MUST ONLY use information from retrieved tool results. NEVER make up names, people, events, or entities.

{role_section}

Your approach:
- Reason over the retrieved memories to answer the question
- Make reasonable inferences when the exact answer isn't explicitly stated
- Connect related memories to form a complete picture
- Be helpful - if you have related information, use it to give the best possible answer
- ONLY use information from tool results - no external knowledge or guessing

Only say "I don't have information" if the retrieved data is truly unrelated to the question.

FORMATTING: Use proper markdown formatting in your answer:
- Headers (##, ###) for sections
- Lists (bullet or numbered) for enumerations
- Bold/italic for emphasis
- Tables with proper syntax (ensure blank line before and after)
- Code blocks where appropriate
- CRITICAL: Always add blank lines before and after block elements (tables, code blocks, lists)
- Proper spacing between sections

CRITICAL: Output ONLY the final synthesized answer. Do NOT include:
- Meta-commentary about what you're doing ("I'll search...", "Let me analyze...")
- Explanations of your reasoning process
- Descriptions of your approach
Just provide the direct answer with proper markdown formatting.

CRITICAL: This is a NON-CONVERSATIONAL system. NEVER ask follow-up questions, offer to search again, suggest alternatives, or end with anything like "Would you like me to..." or "Let me know if...". The user cannot reply. Your answer must be complete and self-contained.r$   c                 r    | r|                                  nt          }t                              |          S )zHBuild the final synthesis system prompt, using mission as role when set.)role_section)r7   _DEFAULT_FINAL_ROLE_FINAL_SYSTEM_PROMPT_BASEformat)r$   rc   s     r   build_final_system_promptrg     s0    &-F7==???3FL$+++FFFr   u  You are integrating *new information* into an existing structured document.

You will be given:
1. TOPIC — the question this document answers. Content that does not help
   answer this question is OFF-TOPIC and should be removed.
2. CURRENT DOCUMENT (JSON) — the existing structured mental model. Each section
   has a stable ``id``, a ``heading``, a ``level`` (1..6), and an ordered list
   of ``blocks``. Blocks are typed: ``paragraph``, ``bullet_list``,
   ``ordered_list``, or ``code``.
3. NEW INFORMATION SYNTHESIS (markdown) — a synthesis showing how the new facts
   relate to the document's topic. Use it to understand context and relevance,
   but do NOT copy its formatting or wording wholesale.
4. SUPPORTING FACTS — observations and facts created since the last refresh.
   These are genuinely new — they were NOT available when the current document
   was written.

Your task: output a JSON object ``{"operations": [...]}``. Applied to CURRENT
DOCUMENT, the operations must produce a document that best answers the TOPIC
by integrating the new facts.

RULES
- These facts are NEW since the last refresh. The existing document already
  captures all prior information from earlier refreshes. Your job is to
  integrate the new facts into the existing document.
- **Preserve existing content**: The current document was built from prior facts
  that you cannot see. Do NOT remove or replace existing sections just because
  the new facts do not reference them. Only remove content when the new facts
  explicitly contradict or supersede it.
- **Merge overlapping topics**: When new facts cover topics that overlap with
  existing sections, merge the new information INTO the existing section
  rather than creating duplicates. When new facts provide more specific or
  authoritative guidance on a topic already covered generically, update the
  existing content to reflect the more specific guidance.
- **Preserve examples**: Concrete examples, before/after pairs, sample sentences,
  and illustrative ✅/❌ comparisons are MORE valuable than abstract rules.
  When facts contain examples, include them. Never drop an example to make
  room for an abstract restatement of the same point.
- Operations target sections by ``section_id`` (use the ``id`` field of the
  section in CURRENT DOCUMENT, NOT the heading). Block operations target
  blocks by ``index`` (0-based, against the section's current block list).
- **Add** new content with ``append_block``, ``insert_block``, or ``add_section``
  when facts introduce information not yet covered. Prefer extending an
  existing section over creating a new one.
- **Update** existing content with ``replace_block`` or ``replace_section_blocks``
  when new facts provide corrections, updates, or more specific information
  about topics already in the document.
- **Remove** content with ``remove_block`` or ``remove_section`` ONLY when
  the new facts explicitly contradict or supersede it.
- NEVER emit operations whose only effect is to reword unchanged content.
- NEVER emit operations to "normalize" formatting (numbered → bulleted, casing
  changes, paragraph → list, etc).
- Every operation MUST be justifiable by a specific fact in SUPPORTING FACTS.
- Output ``{"operations": []}`` only if the new facts are already reflected
  in the document (e.g., from a concurrent update).

ALLOWED OPERATIONS (each line shows the JSON shape)
- ``{"op": "append_block", "section_id": "...", "block": {...}}``
- ``{"op": "insert_block", "section_id": "...", "index": N, "block": {...}}``
- ``{"op": "replace_block", "section_id": "...", "index": N, "block": {...}}``
- ``{"op": "remove_block", "section_id": "...", "index": N}``
- ``{"op": "add_section", "heading": "...", "level": 2, "blocks": [...], "after_section_id": "..."}``
- ``{"op": "remove_section", "section_id": "..."}``
- ``{"op": "replace_section_blocks", "section_id": "...", "blocks": [...]}``
- ``{"op": "rename_section", "section_id": "...", "new_heading": "..."}``

Block shapes
- ``{"type": "paragraph", "text": "..."}``
- ``{"type": "bullet_list", "items": ["...", "..."]}``
- ``{"type": "ordered_list", "items": ["...", "..."]}``
- ``{"type": "code", "language": "json", "text": "..."}``

OUTPUT FORMAT
Return ONLY a single JSON object on its own, with no prose before or after,
no markdown code fences, no commentary. The object must have exactly one
top-level key, ``operations``, whose value is an array of operation objects
(empty array when nothing changes).

Examples
- No changes needed → ``{"operations": []}``
- Add one bullet to an existing "Members" section →
  ``{"operations": [{"op": "append_block", "section_id": "members",
  "block": {"type": "bullet_list", "items": ["Carol — junior engineer"]}}]}``
- Replace a paragraph that has been corrected by new facts →
  ``{"operations": [{"op": "replace_block", "section_id": "overview",
  "index": 0, "block": {"type": "paragraph", "text": "Updated summary."}}]}``
- Remove an obsolete block →
  ``{"operations": [{"op": "remove_block", "section_id": "status", "index": 2}]}``)max_output_tokenscurrent_document_jsoncandidate_markdownsupporting_factssource_queryrh   c           
         g }|D ]}|                     dd          }|                     d          pd                                                    dd          }|                     dd          }	|                    d|	 d| d	|            |rd                    |          nd
}
d}|d| d}d| d|  d| d|
 | d
S )uL  Build the user prompt for a structured-delta mental model refresh.

    The LLM's job is to emit operations against ``current_document_json``;
    the surrounding ``candidate_markdown`` and ``supporting_facts`` are
    references for *what new information exists*, not templates to mimic.

    ``max_output_tokens`` is surfaced in the prompt so the model can keep its
    op list within the provider's response cap. The actual cap is enforced by
    the caller; this is just an advisory anchor — without it the model often
    returns op lists whose JSON gets truncated mid-string.
    idr	   textr    type- [:] (no supporting facts retrieved)Nz7

## Output budget
Your JSON response must fit within ~z tokens. If you would need more than this to express every change, prefer the highest-leverage edits first (a few ``replace_section_blocks`` ops over many block-level ops) so the response always parses as valid JSON.	## Topic
zS

## CURRENT DOCUMENT (apply ops to this; reference section ids as listed)
```json
z_
```

## NEW INFORMATION SYNTHESIS (context for how new facts relate to the topic)
```markdown
uG   
```

## SUPPORTING FACTS (new since last refresh — integrate these)
z

## Task
Output a JSON object matching the operations schema. Integrate the new supporting facts into CURRENT DOCUMENT. Add, update, or remove content as needed. Preserve unchanged sections and blocks by not mentioning them.r   r7   replacer   r   )ri   rj   rk   rl   rh   
fact_linesffidro   ftypefacts_blockbudget_hints               r   build_structured_delta_promptr   i  s@   & J 7 7eeD"oof#**,,44T3??fb!!55555t556666+5\$))J''';\KK$L3DL L L 	
	T\ 
	T 
	T)
	T 
	T +	
	T 
	T
 NY
	T 
	T 
	T 
	Tr   u  You are performing a surgical delta update to an existing mental model document.

You will be given:
1. CURRENT DOCUMENT: the existing mental model content (markdown).
2. CANDIDATE UPDATE: a freshly generated synthesis based on the latest retrieved memories.
3. SUPPORTING FACTS: the observations and facts that support the CANDIDATE UPDATE.

Your task: produce an updated version of the CURRENT DOCUMENT that reflects the new reality, with the MINIMUM possible changes.

ABSOLUTE RULES:
- Preserve unchanged content BYTE-FOR-BYTE. If a sentence, heading, bullet, code block, or section is still accurate according to the CANDIDATE UPDATE and SUPPORTING FACTS, copy it verbatim — same wording, same punctuation, same whitespace, same markdown structure.
- Do NOT reformat, rephrase, or re-style content that is still accurate. No "light edits for clarity", no reordering for flow, no synonym swaps.
- Remove content that is contradicted by the CANDIDATE UPDATE or SUPPORTING FACTS (stale content).
- Add new content ONLY when the SUPPORTING FACTS contain information not already in the CURRENT DOCUMENT.
- When adding new content, prefer appending to an existing relevant section. Creating a new section is acceptable when the new information does not fit any existing section.
- When creating a new section, match the heading style, tone, and formatting conventions used in the CURRENT DOCUMENT.
- Every assertion in your output MUST be grounded in either (a) the CURRENT DOCUMENT (preserved) or (b) the SUPPORTING FACTS. Never introduce outside knowledge.
- If nothing in the SUPPORTING FACTS contradicts or extends the CURRENT DOCUMENT, return the CURRENT DOCUMENT UNCHANGED, character for character.

OUTPUT FORMAT:
- Output ONLY the updated markdown document. No preamble, no explanation, no diff markers, no commentary.
- Do not wrap the output in code fences unless the CURRENT DOCUMENT itself was entirely a code fence.current_contentcandidate_contentc           	      n   g }|D ]}|                     dd          }|                     d          pd                                                    dd          }|                     dd          }|                    d| d| d	|            |rd                    |          nd
}	d| d|  d| d|	 d	S )a  Build the user prompt for a delta-mode mental model refresh.

    Args:
        current_content: The existing mental model content (to preserve as much as possible).
        candidate_content: Fresh synthesis from the reflect agent reflecting new reality.
        supporting_facts: Flat list of fact dicts (id, text, type) supporting the candidate.
        source_query: The mental model's source query, for topical framing.
    rn   r	   ro   r   rp   rq   rr   rs   rt   ru   rv   z"

## CURRENT DOCUMENT
```markdown
z&
```

## CANDIDATE UPDATE
```markdown
z
```

## SUPPORTING FACTS
z

## Task
Produce the updated mental model document by applying the minimum necessary changes to CURRENT DOCUMENT so that it reflects CANDIDATE UPDATE and SUPPORTING FACTS. Preserve unchanged content byte-for-byte. Output only the final markdown.rw   )
r   r   rk   rl   ry   rz   r{   ro   r|   r}   s
             r   build_delta_promptr     s    J 7 7eeD"oof#**,,44T3??fb!!55555t556666+5\$))J''';\K	T\ 	T 	T-<	T 	T->	T 	T !,	T 	T 	T	r   )NNFN)N)NrS   )__doc__rK   typingr   tiktokenget_encodingrZ   rW   r8   rd   listdictrM   r   r   r   boolr<   rR   rV   ra   re   rg   FINAL_SYSTEM_PROMPTSTRUCTURED_DELTA_SYSTEM_PROMPTr   DELTA_SYSTEM_PROMPTr    r   r   <module>r      sq           *X*=99  "% ih d38n)= $s)    d38n)= #    @$tCH~*> 3    @ .2#j jsCx.j4Zj T#s(^$t+j 	j
 $Jj 	j j j jb &*	C CC$ZC C d
	C
 	C C C CT &*%O OO$ZO O d
	O
 O 	O O O OdR >G GsTz GS G G G G 0/11 V"V ~ %)1 1 11 1 4S>*	1
 1 Tz1 	1 1 1 1hi 0     4S>*	 
   	           r   