
    hl!j1                    8   S SK Jr  S SKrS SKrS SKrS SKrS SKrS SKrS SKrS SK	J
r
  S SKJr  S SKJr  Sr\R                   R#                  SS5      r\R                   R#                  S	S
5      r\R                   R#                  SS5      r\R                   R#                  S5      r\" \R                   R#                  SS5      5      r\" \R                   R#                  SS5      5      r\" \R                   R#                  SS5      5      r1 SkrS V s/ s H  n \R9                  U \R:                  5      PM!     sn rS%S jrS&S jr S'S jr!S(S jr"S)S jr#S*S jr$S+S jr%S,S jr&S-S jr'S.S jr(S/S  jr)S0S! jr*S1S" jr+S2S# jr,\-S$:X  a  \." \," 5       5      egs  sn f )3    )annotationsN)Path)Any)requestH   AGENTS_DB_APIzhttp://100.116.176.16:8091PI_SESSION_MEMORY_MODELzgpt-5.4-miniPI_SESSION_MEMORY_THINKINGoffPI_SESSION_MEMORY_PI_BIN PI_SESSION_MEMORY_MAX_CANDIDATES6-PI_SESSION_MEMORY_ACTIVE_IMPORTANCE_THRESHOLDz0.92-PI_SESSION_MEMORY_ACTIVE_CONFIDENCE_THRESHOLDz0.9>   profileprojectartifactdecisionsemantic
procedural)z!you are running one deterministiczphase-machine passzsubagent intake task_z^task id:\s*task_z^payload:\s*\{z"route"\s*:\s*\{zyou are iteration zcontinue the bounded ralph-loopc                    [         [        R                  " S5      [        [        R
                  " 5       S-  S-  S-  5      SS/n U  H.  nU(       d  M  [	        U5      R                  5       (       d  M,  Us  $    [        S5      e)Npiz.npm-globalbinz/usr/local/bin/piz/usr/bin/pi)PI_BINshutilwhichstrr   homeexistsFileNotFoundError)
candidates	candidates     8/home/sebas/pi-config/scripts/session-memory-analyzer.pyresolve_pi_binr$   (   ss    TDIIK-'%/$67J  		?!!##	  
 D
!!    c                H    [         R                  " U R                  SS95      $ )Nutf-8encoding)jsonloads	read_text)job_files    r#   load_jobr.   8   s    ::h(('(:;;r%   c                R    U R                  [        R                  " USSS9S-   SS9  g )N   F)indentensure_ascii
r'   r(   )
write_textr*   dumps)r-   payloads     r#   save_jobr7   <   s(    

715IDP[bcr%   c                r   [        5       SSSS[        S[        SSU /n[        R                  " USSS	9nUR
                  S
:w  a[  [        UR                  R                  5       =(       d1    UR                  R                  5       =(       d    SUR
                   S35      eUR                  R                  5       $ )Nz-pz
--providerzopenai-codexz--modelz
--thinkingz
--no-toolsz--no-sessionT)capture_outputtextr   zpi failed ())
r$   PI_MODELPI_THINKING
subprocessrun
returncodeRuntimeErrorstderrstripstdout)promptcmdprocs      r#   call_pirH   @   s    C >>#d>D!4;;,,.i$++2C2C2Ei;W[WfWfVgghIijj;;r%   c                   [        U 5      nUR                  S5      =(       d    SR                  5       nUR                  S5      =(       d    SR                  5       nUR                  S5      =(       d    U=(       d    SR                  5       nU(       a  U(       d  / SU 3S.$ UR                  5       S   R                  5       n[	        U5      [
        :  a  US [
        S-
   R                  5       S	-   nUR                  S
5      =(       d    Sn[        U5      R                  =(       d    SnSSUR                  S5      =(       d    SU SU 3SU SU 3SUR                  S5      =(       d?    [        [        UR                  S5      =(       d    S5      5      R                  =(       d    S 3UR                  S5      SSSSU 3S./SU 3S.$ )Nlast_user_text last_assistant_textfirst_user_textzfallback-no-summary:)memoriesreasonr      u   …cwdsessionepisodesession_summaryscoper   z: zUser asked: z	
Result: zsession:
session_idsession_fileunknowng
ףp=
?gffffff?gQ?z?Deterministic fallback because model analysis was unavailable: )typesubtyperU   titlecontent
source_refevidence_ref
confidence	freshness
importancerO   zfallback-analysis:)session_metagetrC   
splitlineslenFALLBACK_TITLE_MAXrstripr   namer   stem)	joberrormeta	last_userlast_assistant
first_user
title_baserQ   cwd_names	            r#   fallback_analysisrr   T   s   D*+1r88:Ihh45;BBDN((,-@@bGGIJ^,@*HII&&(+113J
:++ 8"4q"89@@BUJ

((5/
RCCy~~*H ",'*7i$:R
|4)*Z?OP (,)?)~4DHHUcLdLjhjHkClCqCq)~u~(  A $ 8"!"[\a[bc
 'ug.! r%   c                L   [         R                  " [         S3S[        R                  " U 5      R                  5       SS0S9n[         R                  " USS9 n[        R                  " UR                  5       R                  S5      5      sS S S 5        $ ! , (       d  f       g = f)	Nz/api/ingestPOSTzContent-Typezapplication/json)methoddataheaders   )timeoutr'   )
r   Requestr   r*   r5   encodeurlopenr+   readdecode)memoryreqresps      r#   ingestr   t   sv    
///%ZZ&&(!34	C 
b	)Tzz$))+,,W56 
*	)	)s   3B
B#c                >   U R                  5       nUR                  S5      (       a.  UR                  S5      nSU;   a  UR                  SS5      S   OUnUR                  S5      nUR	                  S5      nUS:  a  X2:  a  XUS-    n[
        R                  " U5      $ )	Nz````r3   rP   {}r   )rC   
startswithsplitfindrfindr*   r+   )r:   rawstartends       r#   extract_jsonr      s    
**,C
~~eiin(,ciia $HHSME
))C.Czck#'"::c?r%   c                V    U R                  S5      n[        U[        5      (       a  U$ U $ )Nr6   )rc   
isinstancedict)rj   r6   s     r#   rb   rb      s'    ggi G'4  Jr%   c                J   [        U 5      nS[         SUR                  S5       SUR                  S5       SUR                  S5       SUR                  S	5       S
UR                  S5       SUR                  S5       SUR                  S5       S[        UR                  S5      =(       d    S5      S S  S[        UR                  S5      =(       d    S5      S S  SUR                  S5       S[        R
                  " UR                  S5      =(       d    / SS9S S  S3$ )NzYou are extracting reusable memory candidates from a Pi session.

Goal:
- Prefer broad candidate capture over premature rejection.
- Return 0 to a   memories from this session.
- Include strong durable memories and weaker candidate memories that may be worth later consolidation.

Rules:
- Session metadata alone is not enough.
- Do NOT save operational notes about this session-memory system, dispatch flow, or local implementation work unless they affect broader workflows beyond this repo.
- Favor stable user preferences, enduring project facts, reusable external artifacts, decisions, procedures, blockers, and compact episode summaries with future reuse value.
- It is OK to include lower-confidence candidates if they could become useful after consolidation.
- Avoid trivial chatter, one-off execution noise, and duplicates of the same point unless they capture materially different memories.
- Prefer at most one memory per distinct insight.
- Output JSON only. No markdown. No extra text.

Return this schema:
{
  "memories": [
    {
      "type": "profile" | "decision" | "project" | "artifact" | "episode" | "procedural" | "semantic",
      "subtype": string | null,
      "scope": "global" | "project",
      "title": string,
      "content": string,
      "source_ref": string,
      "evidence_ref": string | null,
      "confidence": number,
      "freshness": number,
      "importance": number,
      "reason": string
    }
  ],
  "reason": string
}

Scoring guidance:
- confidence: 0 to 1, how well supported the memory is.
- freshness: 0 to 1, how current it is.
- importance: 0 to 1, how much future value it has.
- evidence_ref: cite the strongest source in the session or branch excerpt when possible.
- Use lower confidence/importance for tentative candidates rather than omitting them.

Session metadata:
- session_id: rV   z
- session_file: rW   z
- cwd: rQ   z

- scope: rU   z
- reason: rO   z
- user_messages: user_messagesz
- assistant_messages: assistant_messagesz
- last_user_text: rJ   rK   i  z
- last_assistant_text: rL   z
- trigger: triggerz

Branch excerpt JSON:
branchFr2   i0u  r3   )rb   MAX_CANDIDATESrc   r   r*   r5   )rj   rl   s     r#   build_promptr      sH   D  (P xx%& '.)* + 

((7
	 88H
 ((?+, -xx 456 7txx 017R8$?@ ADHH%:;ArB5DIJ KHHY  ! DHHX$"59&5A B Cq9 9r%   c                    U R                  S5      n[        U[        5      (       a*  U Vs/ s H  n[        U[        5      (       d  M  UPM     sn$ [	        U R                  S5      5      (       a  U /$ / $ s  snf )NrN   save)rc   r   listr   bool)analysisrN   items      r#   normalize_memoriesr      sb    ||J'H(D!!!)DZd-CDDHLL !!zI Es   A5A5c                B    U [         ;   a  U[        :  a  U[        :  a  gg)Nactiveinbox)DURABLE_TYPESACTIVE_CONFIDENCE_THRESHOLDACTIVE_IMPORTANCE_THRESHOLD)memory_typer_   ra   s      r#   choose_statusr      s!    m#
6Q(QV`dVr%   c                  ^ [        U R                  S5      =(       d    S5      n[        U R                  S5      =(       d    S5      nU SU 3R                  5       mT(       d  gTR                  5       n[	        U4S j[
         5       5      (       a  gUR                  S5      S:  a  gUR                  S	5      S
:  a  UR                  S5      S
:  a  gUR                  5        Vs/ s H)  oDR                  5       (       d  M  UR                  5       PM+     nnU(       a%  [        S U 5       5      nU[        U5      -  S:  a  ggs  snf )Nr[   rK   r\   r3   Tc              3  D   >#    U  H  oR                  T5      v   M     g 7f)N)search).0patternblobs     r#   	<genexpr>"is_noise_memory.<locals>.<genexpr>   s     
>~G>>$~s    task_r0   zpayload:rP   routec              3  `   #    U  H$  oR                  S 5      (       d  SU;   d  M   Sv   M&     g7f))zPayload:r   r   "r   rP   N)r   )r   lines     r#   r   r      s(     iED__=X-Y-Y]`dh]haaEs   .	.g?F)
r   rc   rC   loweranyNOISE_PATTERNScountrd   sumre   )r"   r[   r\   loweredr   linesjsonishr   s          @r#   is_noise_memoryr      s   	g&,"-E)--	*0b1GWBwi &&(DjjlG

>~
>>>}}W"}}Z A%'--*@A*E&-&8&8&:K&:djjl\TZZ\&:EKiEiiSZ4' Ls   'EEc                   U R                  S5      =(       d    Sn[        U R                  S5      =(       d    S5      n[        U R                  S5      =(       d    S5      n[        XVU5      nUU R                  S5      U R                  S5      =(       d    UR                  S5      =(       d    S	US
U R                  S5      =(       d    SU 3U R                  S5      =(       d    SU[        U R                  S5      =(       d    S5      UU R                  S5      =(       d5    SUR                  S5      =(       d    UR                  S5      =(       d    S 3U R                  S5      S[        U5      UR                  S5      UR                  S5      UR                  S5      UR                  S5      UR                  S5      UR                  S5      UU R                  S5      UR                  S5      US:H  US.S.$ ) NrY   rS   r_   g333333?ra   g      ?rZ   rU   globalmanualr[   zSession insight r\   rK   r`   g?r]   zpi-session:rW   rV   rX   r^   zpi-session-memory-analyzerrQ   rO   r   r   r   r   )r-   rV   rW   rQ   rO   r   r   analysis_reasoncandidate_reasonr   promotion_candidatesession_candidate_index)rY   rZ   rU   statussource_kindr[   r\   r_   r`   ra   r]   r^   origin_agentmetadata)rc   floatr   r   )	r"   rl   r-   r   indexr   r_   ra   r   s	            r#   build_memory_payloadr      s   --'49Ky}}\29c:Jy}}\29c:J;J?F==+w'H488G+<Hw'E-=eW+E==+1r 9==5<= mmL1  E{488NC[  DC_c_g_ght_u  DC  zC  CD  6E!n54H((<0 HH^488E?hhx(!XXo6"&((+?"@. )h 7xx	*#)W#4',
 r%   c            	        [         R                  " 5       n U R                  SSS9  U R                  5       n[	        UR
                  5      n[        U5      n[        U5      nSUS'   SS S S / SS.US'   [        X#5         S n [        [        U5      5      n[        U5      n[!        U5      S ["         n	/ n
[%        U	SS9 H  u  p['        U5      (       a  M  [)        XX'R+                  S5      U5      nUS   R-                  5       (       a  US   R-                  5       (       d  Me  U
R/                  [1        U5      5        M     XcS   S'   XsS   S'   SUS   S'   SUS'   Ub  [3        U5      US   S'   [5        U
5      US   S'   [5        U
5      US   S'   [7        U
5      US   S'   U
 Vs/ s H+  oR+                  S5      (       d  M  UR+                  S5      PM-     snUS   S'   US   S   (       a  US   S   S   OS US   S'   [        X#5        [9        [        R                  " US   S	S
95        g! [         a-  nUn[        X85      n[        R                  " US	S
9n S nAGNS nAff = fs  snf ! [         aa  nSUS'   SUS   S'   [3        U5      US   S'   [        X#5        [9        [        R                  " US   S	S
9[:        R<                  S9   S nAgS nAff = f)Nz
--job-fileT)requiredrunningr   r   )r   r   saved	memory_id
memory_idssaved_countr   Fr   rP   )r   rO   r\   r[   r   result	completedfallback_errorr   r   r   idr   r   failedrk   )file)argparseArgumentParseradd_argument
parse_argsr   r-   r.   rb   r7   rH   r   r   	Exceptionrr   r*   r5   r   r   	enumerater   r   rc   rC   appendr   r   r   re   printsysrB   )parserargsr-   rj   rl   r   r   r   excr!   saved_itemsr   r"   r   r   s                  r#   mainr     s   $$&F
t4DDMM"H
8
CDCMC
O X)	;,s+,C#C(H
 (1/>B
,. )*A >Ey))))8\\RZE[]bcF)$**,,F7O4I4I4K4Kvf~. !? "%J$,J!$/J!#H%03N0CC
O,-"&{"3J#'#4J ),[)9J&DO(bKDS[S[\`Sa$K(bJ%KNz?[gKhs:|'DQ'GnrJ$djjZu=>;  	; N(2H**XE:C	;0 )c   H$,J!#&s8J djjZu=CJJOsW   >I. H/  DI. 'I)I)AI. /
I&9"I!I. !I&&I. .
K8AKK__main__)returnr   )r-   r   r   dict[str, Any])r-   r   r6   r   r   None)rE   r   r   r   )rj   r   rk   r   r   r   )r   r   r   r   )r:   r   r   r   )rj   r   r   r   )rj   r   r   r   )r   r   r   zlist[dict[str, Any]])r   r   r_   r   ra   r   r   r   )r"   r   r   r   )r"   r   rl   r   r-   r   r   z
str | Noner   intr   r   )r   r   )/
__future__r   r   r*   osrer   r>   r   pathlibr   typingr   urllibr   rf   environrc   r   r<   r=   r   r   r   r   r   r   r   compile
IGNORECASEr   r$   r.   r7   rH   rr   r   r   rb   r   r   r   r   r   r   __name__
SystemExit)r   s   0r#   <module>r      st   "   	 	   
    

0LM::>>3^Djjnn95A	2	3RZZ^^$FLM#BJJNN3bdj$kl #BJJNN3bdi$jk X		 JJw&	" <d(@7	;|*!H<~ z
TV
 }	s   &F