
    zl!j                       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Jr  S SK	J
r
J	r	Jr  S SKJr  S SKJr  SSKJr  SS	KJr  SS
 jrSS jrSS jrSS jrSS jr\" SS9 " S S5      5       r " S S5      rg)    )annotationsN)	dataclass)UTCdatetime	timedelta)Any)urlparse   )SCHEMA_VERSION)SQLiteStorec                 R    [         R                  " [        5      R                  5       $ N)r   nowr   	isoformat     >/home/sebas/agents-database/src/shared_agent_memory/service.pyutcnowr      s    <<&&((r   c                J    U  S[         R                  " 5       R                   3$ )N_)uuiduuid4hex)prefixs    r   make_idr      s     XQtzz|''())r   c                \    SR                  U R                  5       R                  5       5      $ )N )joinlowersplit)values    r   normalize_textr"      s     88EKKM'')**r   c                (   U R                  5       n[        R                  " SSU5      n[        R                  " SSU5      n[        R                  " SSU5      n[        R                  " SSU5      n[        R                  " S	S
U[        R                  [        R                  -  S9n[        R                  " SSU[        R                  [        R                  -  S9n[        R                  " SSU5      nSR                  UR                  5       5      $ )Nz\[telegram\]r   zhttps?://\S+z URL z&\b(task|run|job|session)_[a-z0-9_-]+\bz ID z\b\d{4}-\d{2}-\d{2}[t ][^\s]+\bz TS zpayload:\s*\{.*z payload_json )flagsz"route"\s*:\s*\{.*z route_json z[^\w\s])r   resub
IGNORECASEDOTALLr   r    )r!   texts     r   normalize_for_deduper*      s    ;;=D66/3-D66/7D1D66;VTJD664fdCD66$&6BMMTVT]T]D]^D66'R]]UWU^U^E^_D66*c4(D88DJJL!!r   c                    U S3nU R                  5        H7  nUR                  U5      (       d  M  U[        U5      S  R                  5       s  $    g)N: )
splitlines
startswithlenstrip)contentlabelr   lines       r   _line_valuer5   )   sN    wa[F""$??6""F&,,.. % r   T)slotsc                  \    \ rS rSr% S\S'   S\S'   S\S'   S\S'   S\S	'   S\S
'   SS jrSrg)SearchResult1   dict[str, Any]memoryfloatscorestrexplanationfacet_scorelexical_scoresemantic_scorec                    U R                   U R                  U R                  U R                  U R                  U R                   S   U R                   S   S.U R                   S   U R                   S   U R
                  S.$ )N
confidence	freshness)facetlexicalsemanticrD   rE   scopeevidence_ref)r;   r=   score_breakdownmatched_scoperJ   r?   )r;   r=   r@   rA   rB   r?   )selfs    r   as_dictSearchResult.as_dict:   su    kkZZ))-- //"kk,7![[5  "[[1 KK7++
 	
r   r   Nreturnr:   )__name__
__module____qualname____firstlineno____annotations__rN   __static_attributes__r   r   r   r8   r8   1   s*    L
r   r8   c                     \ rS rSrSeS jrSfS jrSfS jrSgS jr Sh           SiS jjr    Sj           SkS	 jjr	 Sl         SmS jjr
SnS jrSoS jr Sp         SqS jjrSrS jrSsS jrStS jrSuS jrSSSSSSSSSSSSSSSS.                               SvS jjrSwS jrSpSxS jjrSySzS jjrSpS{S jjrS
SSSSSSSSSSSSSS.                                 S|S jjrS}S jrSSSSSS .           S~S! jjrSSSSSSS".               SS# jjrSSS$.         SS% jjrSS& jrSSS'.         SS( jjrSSSS).SS* jjrS+SSSSS,.                   SS- jjrSS. jr SSS/.SS0 jjr!SS1.SS2 jjr"S}S3 jr#SsS4 jr$SsS5 jr%              SS6 jr&SS7 jr'SS8 jr(SS9 jr)SS: jr*SS; jr+SS< jr,SwS= jr-SSS>.SS? jjr.SS@ jr/SSSSSSSSSSSA.
                       SSB jjr0SSC.           SSD jjr1SSE jr2SSSSF.           SSG jjr3SSH jr4SSISJ.SSK jjr5SSL jr6SSM jr7SSN jr8SSO jr9SSP jr:SSQ jr;SSR jr<SSS jr=SST jr>SSU jr?SSSV jjr@SSW jrASSX jrBSSY jrCSSSZ jjrDSS[ jrESS\ jrFSS] jrG            SS^ jrHSS_ jrISS` jrJSSa jrKSSb jrL          SSc jrMSdrNg)MemoryServiceK   c                    [        U5      U l        SU l        U R                  R                  5         U R	                  5         U R                  5         U R                  SS9  g )NF
   limit)r   store_maintenance_check_running
initialize
migrate_v2_ensure_default_jobs_run_opportunistic_maintenance)rM   db_paths     r   __init__MemoryService.__init__L   sM     )
*/'

!!#++"+5r   c                   [        5       n[        UR                  S5      =(       d    0 5      nUR                  S5      nUR                  S5      nUR                  S5      nUR                  S5      nUR                  S5      =(       d    U(       a  [        U5      R                  OS nUR                  S5      =(       d)    UR                  S5      =(       d    UR                  S5      n	0 S	UR                  S	[        S
5      5      _SUR                  S[        5      _SUS   _SU_SUS   _SUR                  SS5      _SUR                  S5      _SUR                  S5      _SUR                  S5      _SU	_SU_SU_SU_SU_SUR                  SS5      _SUS   _SUS   _UR                  S5      =(       d    U R                  US   5      [        UR                  SS5      5      [        UR                  SS5      5      UR                  SU5      UUR                  SU5      UR                  S5      UR                  S5      U R                  UR                  S5      5      U R                  R                  U5      S.
En
U R                  R                  5        nUR                  S U
5        U R                  X5        S S S 5        U R                  S!S"9  U R!                  U
S	   5      $ ! , (       d  f       N1= f)#Nmetadatasubtyperun_idtask_idurldomainorigin_agentagent_ididmemschema_versiontyperI   statusactive
project_idrepo_idsource_kindmanualtitler2   summaryrD         ?rE   
created_atobserved_at
source_refrJ   	embedding)
r|   rD   rE   r~   
updated_atr   r   rJ   embedding_jsonmetadata_jsona1  
                INSERT OR REPLACE INTO memories (
                    id, schema_version, type, subtype, scope, status, project_id, repo_id, agent_id, origin_agent,
                    run_id, task_id, url, domain, source_kind, title, content, summary, confidence, freshness,
                    created_at, updated_at, observed_at, source_ref, evidence_ref, embedding_json, metadata_json
                ) VALUES (
                    :id, :schema_version, :type, :subtype, :scope, :status, :project_id, :repo_id, :agent_id, :origin_agent,
                    :run_id, :task_id, :url, :domain, :source_kind, :title, :content, :summary, :confidence, :freshness,
                    :created_at, :updated_at, :observed_at, :source_ref, :evidence_ref, :embedding_json, :metadata_json
                )
                r
   r]   )r   dictgetr	   netlocr   r   _make_summaryr<   _encode_embeddingr_   dumps
connectionexecute_upsert_ftsrd   
get_memory)rM   memory_inputr   ri   rj   rk   rl   rm   rn   ro   recordconns               r   create_memoryMemoryService.create_memoryT   s!   h((4:;""9-!!(+""9-u%!!(+V0D0DQU#''7w8<<;Ww[g[k[klv[w
,""48
l../?P
 L(
 w	

 \'*
 l&&x:
 ,**<8
 |''	2
 ((4
 L
 f
 w
 3
 f
 <++M8D
  \'*!
" |I.#
$ $''	2ad6H6HV_I`6a 0 0s CD|//SAB&**<='++M3?&**<8(,,^<"44\5E5Ek5RS!ZZ--h77
: ZZ""$LL
  T* %  	++!+4vd|,,# %$s   $K++
K9c                $    U R                  U5      $ r   )r   )rM   r   s     r   ingestMemoryService.ingest   s    !!,//r   c           	     *    U R                  SSUUUUS9$ )Nsession_closeruntrigger_typery   r   rI   r2   ri   _capture_source)rM   r   rI   r2   ri   s        r   capture_sessionMemoryService.capture_session   s,    ##(! $ 
 	
r   c           	     6    SU0UEnU R                  SSUUUUS9$ )Ncapture_modeconversation_captureconversationr   r   )rM   r   rI   r2   r   ri   s         r   capture_conversation"MemoryService.capture_conversation   s=     #L=H=##/&! $ 
 	
r   NFc                N   U=(       d    0 n[        U5      R                  5        Vs/ s H  of(       d  M  UPM     nnS/n/ n	U(       a<  UR                  SSR                  S U 5       5       S35        U	R	                  U5        U(       d"  UR                  S5        U	R                  S5        U	R	                  U R                  X5      5        U R                  R                  5        n
U
R                  SR                  U5      U	5       Vs/ s H  oR                  U5      PM     nnS S S 5        / nU(       a  U R                  U5      O/ nW H  n[        SR                  US	   US
   US   /5      5      nU R                  X5      nU(       a   U R                  XR                  S5      5      OSnU R                  X5      nU(       a  US:X  a  US:X  a  US:X  a  M  US-  US-  -   US-  -   US   S-  -   US   S-  -   nSUS SUS SUS SUS   S SUS   S 3
nUR                  [        UUUUUU5      5        M     [!        US SS9S U nU Vs/ s H  nUR#                  5       PM     nn[%        S5      nU R                  R                  5        n
U
R                  S UUU R                  R'                  X#US!.5      U R                  R'                  U5      [)        5       45        S S S 5        UUS".$ s  snf s  snf ! , (       d  f       GN= fs  snf ! , (       d  f       N4= f)#N SELECT * FROM memories WHERE 1=1zAND scope IN (,c              3  &   #    U  H  nS v   M	     g7f?Nr   .0r   s     r   	<genexpr>'MemoryService.search.<locals>.<genexpr>   s     0Eff   )AND status = ?rv   r   r{   r|   r2   r           r   g?g333333?g333333?rD   gQ?rE   g{Gz?zfacets=z.2fz	 lexical=z
 semantic=z confidence=z freshness=c                    U R                   U R                  U R                  U R                  S   U R                  S   U R                  S   4$ )NrD   rE   r   )r@   rA   rB   r;   )items    r   <lambda>&MemoryService.search.<locals>.<lambda>   sF      ""##L)K(L)r   T)keyreverseretzjINSERT INTO retrieval_logs (id, query_text, filters_json, results_json, created_at) VALUES (?, ?, ?, ?, ?))scopesfiltersinclude_inbox)retrieval_idresults)r"   r    appendr   extend_memory_filter_sqlr_   r   r   _row_to_memory_text_embedding_lexical_score_semantic_scorer   _facet_scorer8   sortedrN   r   r   r   )rM   queryr   r   r^   r   termquery_termssqlparamsr   rowrowsr   query_embeddinghaystackrG   rH   rF   r=   r?   orderedr   payloadr   s                            r   searchMemoryService.search   s    -R(6u(=(C(C(EN(Et(EN12JJ0Ef0E(E'FaHIMM&!JJ'(MM(#d--c;<ZZ""$8<SXXc]TZ8[\8['',8[D\ % ')9D$..u5"C%chhGc)ncR[n/]&^_H))+@GVat++OWW[=QRgjH%%c3Ew!|A%1*DL7S=08d?BSEVY]E]]`cdo`psw`wwE%Igc]*XcN S!,/4KK@PQT?UW  NN<UKQYZ[   
 5 /66gd4<<>g6u~ZZ""$LL| JJ$$]j%klJJ$$W-H	 % !-AAs O ] %$> 7 %$s;   
K5K5($K?K:&K?LAL:K??
L
L$taskc           	     
   U R                  SSSSS9nXS.nU R                  SU(       a  SOS SUUSS	9nU R                  SUUS
S9nU V	s/ s H  oS   S;   d  M  U	PM     sn	S S
 nU R                  SSUUSS9n
U R                  SSUUUSS9nU(       a!  U(       d  U R                  U0 UESS0ESS9S   n/ UQUQUQU
Q V	s/ s H'  n	[        U	[        5      (       d  M  SU	;   d  M"  U	S   PM)     nn	UUUU
UUUS.$ s  sn	f s  sn	f )Nrv   globalprofile   )ru   rI   memory_typer^   )rw   rx   projectdecision)ru   rI   r   rw   rx   r^      )ru   rw   rx   r^   rt   >   episoder   artifactr   r   r\   )ru   r   rw   rx   r^   r   )ru   r   rw   rx   rl   r^      )r   r^   r   rq   )profile_factsproject_memoriesactive_decisionsrecent_episodestask_relevant_artifacts	citationsrp   )list_memoriesr   
isinstancer   )rM   r   repoagentr   r   project_filtersr   r   r   r   r   r   s                r   context_forMemoryService.context_for   s    **((Xaij*k)0B--&)D" . 
  --	 . 
 .>  A-=TfQAD-=  A  BE  CE  F,,! - 
 #'"4"4" #5 #
 /&*kk$@g?@gTZ\f@gopk&qr{&|# a-`*:`=M`P_`
`$% *.$, DJ` 	 
 + 0 0.'>"
 	
/ A$
s   
C;C;D D &	D c                   / n/ nU R                   R                  5        nU GH  nUR                  SU45      R                  5       nUc  M*  U R	                  U5      nUR                  SXWS   US   US   45      R                  5       nU(       a  [        S5      n	UR                  SU	UUS   S	[        5       U R                   R                  S
S05      45        UR                  SS[        5       U45        UR                  XXS   S	S.5        M  UR                  SS[        5       U45        UR                  U5        GM     S S S 5        X#S.$ ! , (       d  f       N= f)N#SELECT * FROM memories WHERE id = ?a  
                    SELECT id FROM memories
                    WHERE id != ?
                      AND status = 'active'
                      AND type = ?
                      AND scope = ?
                      AND content = ?
                    LIMIT 1
                    rt   rI   r2   lnkz
                        INSERT INTO memory_links (id, from_memory_id, to_memory_id, relation, created_at, metadata_json)
                        VALUES (?, ?, ?, ?, ?, ?)
                        rq   
related_toreasonexact_duplicate;UPDATE memories SET status = ?, updated_at = ? WHERE id = ?archived)fromtorelationrv   )promotedlinked)	r_   r   r   fetchoner   r   r   r   r   )
rM   inbox_itemsr   r   r   	memory_idr   r;   	duplicatelink_ids
             r   consolidateMemoryService.consolidate  sm    ')ZZ""$(	ll#H9,W``b;,,S1 LL vw	ARS (*  %enGLL
 $%%dO("H JJ,,h8I-JK LL!^akmsmu  xA  aB  CMM9dOYe"fgZ]egmgoqz\{|	*K ) %N %77O %$s   D#E
Ec               
   SSSSSSS.n[        UR                  SS5      5      n[        UR                  SS5      5      n[        UR                  SS5      5      n[        UR                  S	S
5      5      n[        UR                  SS5      5      n[        UR                  SS5      5      n[        UR                  SS5      5      n	UR                  S5      =(       d    Sn
UR                  S5      =(       d    / SQn[        R
                  " [        5      [        US9-
  R                  5       nU R                  R                  5        nUR                  SX45      R                  5       nU Vs/ s H  oR                  U5      PM     nn[        U5      US'   U GH;  nUR                  SUS   US   US   45      R                  5       nU Vs/ s H  oR                  U5      PM     nn[        US   5      nS nSnU H  n[        US   5      nU R!                  UR#                  5       U5      nU R%                  UR                  S5      =(       d    / UR                  S5      5      nUS:X  a  UO
US-  US -  -   nUU:  d  M  UnUnM     U(       aj  U[        US   5      :X  aX  U R'                  UUS   US   S!S"5        UR                  S#S$[)        5       US   45        US$==   S%-  ss'   US&==   S%-  ss'   GMb  U(       a^  UU:  aX  U R'                  UUS   US   S!S'5        UR                  S#S$[)        5       US   45        US$==   S%-  ss'   US&==   S%-  ss'   GM  U(       a  UU:  a  U	(       a  U R+                  UUU
US(9nU(       ag  UR                  S)U[)        5       U R                  R-                  0 UR                  S*0 5      EUS   US   /U
US+.E5      US   45        US,==   S%-  ss'   U R'                  UUS   US   S!S-5        US&==   S%-  ss'   U(       a_  UU:  aY  U R/                  UU5      (       aB  U R1                  UUS   US   S.5        U R'                  UUS   US   S/S05        US1==   S%-  ss'   US2   S3:X  d  GM  UR                  S4S5      U:  d  GM  UR                  S#S5[)        5       US   45        US6==   S%-  ss'   GM>     S S S 5        U$ s  snf s  snf ! , (       d  f       U$ = f)7Nr   )
candidatesr   r   r   	conflictsllm_summariescandidate_age_days   max_candidates   dedupe_high_threshold?dedupe_mid_threshold      ?promote_confidenceffffff?conflict_threshold皙?llm_enabledFllm_provideropencodellm_commandr  z-mzMiniMax M2.5 Freedaysa-  
                SELECT * FROM memories
                WHERE (
                    status = 'inbox'
                    OR (type = 'episode' AND status = 'active')
                )
                  AND created_at <= ?
                ORDER BY created_at ASC
                LIMIT ?
                r  a  
                    SELECT * FROM memories
                    WHERE status = 'active'
                      AND id != ?
                      AND type = ?
                      AND scope = ?
                    ORDER BY updated_at DESC
                    LIMIT 50
                    rq   rt   rI   r2   r   r   g333333?g?r   r   r   r   r
   r   high_similarity)providercommandzOUPDATE memories SET summary = ?, updated_at = ?, metadata_json = ? WHERE id = ?ri   )synthesis_sourcessynthesis_providersynthesis_commandr  mid_similaritypotential_contradictioncontradicts	heuristicr  ru   inboxrD   rv   r   )intr   r<   boolr   r   r   r   r   r_   r   r   fetchallr   r0   r*   r   r    r   _link_memoriesr   _llm_summarize_pairr   _conflict_signal_record_conflict)rM   configstatsage_daysr	  high_thresholdmid_thresholdpromote_thresholdr  r  r  r  cutoffr   r   r   r  	candidaterelatedrelated_memoriescandidate_norm
best_match
best_scoreother
other_normrG   rH   r=   synthesizeds                                r   consolidate_candidates$MemoryService.consolidate_candidatesK  s)   
 vzz"6:;VZZ(8#>?vzz*A3GHfjj)?FG!&**-A3"GH"6::.BD#IJ6::mU;<zz.1?Zjj/Z3Z,,s#iX&>>IIKZZ""$<<	 ( hj  ?CCds--c2dJC"%j/E,'	,, t_i&779KL (*  IP#P$7$7$< #P!5i	6J!K!
 
-E!5eI6F!GJ"11.2F2F2H*UG#33IMM+4N4TRTV[V_V_`kVlmH'/3GWs]XX[^=[Ez)%*
%*
 . .4HT]I^4_"_''ioz$?OQ]_pqLLU#VXy? *%*%(Oq(O*">''ioz$?OQ]_pqLLU#VXy? *%*%(Oq(O*"="&*&>&>%&%1$/	 '? ' ' LL q$/$*H$(JJ$4$4)*.7mmJ.K)*BKD/S]^bScAdBNAL	)*%& %.dO!"  "/2a72''ioz$?OQ]_op(Oq(O*0B"BtG\G\]fhrGsGs))$	$DAQSlm''ioz$?OQ^`kl+&!+&X&'1immLRU6VZk6kLLU!68Yt_= *%*%m (% %T w D  $Q? %$T s?   	&S//S%	AS/S*)BS/HS/S/)2S/%
S//
S>c                X    U R                  SSUUU R                  U5      UUSS0S.5      $ )Nr   r   kindprofile_fact)rt   rI   r{   r2   r|   r   rJ   ri   )r   r   )rM   r{   r2   rJ   r   s        r   upsert_profile_fact!MemoryService.upsert_profile_fact  sD     !!!!"--g6( ,#^4	
 	
r   c           	        U R                   R                  5        nUR                  SU45      R                  5       nU(       aO  SUS   US   U R                   R	                  US   5      U R                   R	                  US   5      S.sS S S 5        $ UR                  SU45      R                  5       nU(       aa  U R                  U5      nUR                  S	US
   US
   45      R                  5       nSXV Vs/ s H  n[        U5      PM     snS.sS S S 5        $  S S S 5        [        SU 35      es  snf ! , (       d  f       N!= f)Nz)SELECT * FROM retrieval_logs WHERE id = ?	retrievalrq   
query_textfilters_jsonresults_json)r?  rq   rE  r   r   r   z4SELECT * FROM sources WHERE source_ref = ? OR id = ?r   r;   )r?  r;   sourceszUnknown identifier: )	r_   r   r   r   loadsr   r'  r   KeyError)rM   
identifierr   rD  r;   rr   rH  sources           r   explainMemoryService.explain  sP   ZZ""$%PS]R_`iikI'#D/"+L"9#zz//	.0IJ#zz//	.0IJ %$ \\"G*W``bF))&1,,']`cdp`qsv  xD  tE  `F  G  P  P  R (C`gDh`gV\T&\`gDhi %$  % -j\:;; Ei %$s%   A.D8A&D89D3
D83D88
Ec                   / SQn0 nU R                   R                  5        nU HC  nUR                  SU 35      R                  5       nU Vs/ s H  n[	        U5      PM     snX$'   ME     S S S 5        U$ s  snf ! , (       d  f       U$ = f)NprojectsreposrH  ingestion_eventsmemoriesmemory_linksmemory_conflictsretrieval_logsmaintenance_jobsmaintenance_runsprofilestasks	task_runs	artifactszSELECT * FROM r_   r   r   r'  r   )rM   tablesexportedr   tabler   r   s          r   exportMemoryService.export  s    
  57ZZ""$||nUG$<=FFH8<"=49"=   %  #> %$ s   ,A:A5"	A:5A::
B	c                V  ^	 / SQnU R                   R                  5        nU H  nUR                  U/ 5      nU(       d  M  [        US   R	                  5       5      nSR                  S U 5       5      nSU SSR                  U5       SU S3nUR                  X V	^	s/ s H  m	[        U	4S	 jU 5       5      PM     sn	5        US
:X  d  M  U H  m	U R                  UT	5        M     M     S S S 5        U R                  5         U R                  SS9  g s  sn	f ! , (       d  f       N3= f)NrP  r   r   c              3  &   #    U  H  nS v   M	     g7fr   r   r   s     r   r   ,MemoryService.import_data.<locals>.<genexpr>  s     &<GqsGr   zINSERT OR REPLACE INTO z (z
) VALUES (r   c              3  F   >#    U  H  nTR                  U5      v   M     g 7fr   r   )r   colr   s     r   r   rf    s     ,MWcSWWS\\Ws   !rT  r\   r]   )r_   r   r   listkeysr   executemanytupler   rb   rd   )
rM   r   r_  r   ra  r   columnsplaceholderr   r   s
            `r   import_dataMemoryService.import_data  s   
  ZZ""${{5"-tAw||~.!hh&<G&<</wb'9J8K:VaUbbcd  Y]&^Y]RUu,MW,M'MY]&^_J&#((s3  $   % 	++"+5 '_ %$s$   B D D?DDD
D(c                    U R                   R                  5        nUR                  SU45      R                  5       nUc  [	        U5      eU R                  U5      sS S S 5        $ ! , (       d  f       g = f)Nr   )r_   r   r   r   rJ  r   )rM   r   r   r   s       r   r   MemoryService.get_memory%  sZ    ZZ""$,,DylS\\^C{y))&&s+	 %$$   A A%%
A3rv   2   )ru   rI   r   rj   rw   rx   r   rJ   rk   rl   ro   rm   rn   ri   r^   c               L   S/n/ nUb"  UR                  S5        UR                  U5        Ub"  UR                  S5        UR                  U5        UUUUUUU	U
UUUS.nUR                  U R                  UUR                  5        VVs0 s H  u  nnUc  M  UU_M     snn5      5        U=(       d    0 R                  5        H-  u  nnUR                  S5        UR                  SU 3U45        M/     UR                  S5        UR                  U5        U R                  R                  5        nUR                  SR                  U5      U5      R                  5       nU Vs/ s H  nU R                  U5      PM     snsS S S 5        $ s  snnf s  snf ! , (       d  f       g = f)	Nr   r   zAND scope = ?)rt   rj   rw   rx   r   rJ   rk   rl   ro   rm   rn   z&AND json_extract(metadata_json, ?) = ?z$.z ORDER BY updated_at DESC LIMIT ?r   )
r   r   r   itemsr_   r   r   r   r'  r   )rM   ru   rI   r   rj   rw   rx   r   rJ   rk   rl   ro   rm   rn   ri   r^   r   r   r   r   r!   r   r   r   s                           r   r   MemoryService.list_memories,  s   & 22JJ'(MM&!JJ'MM% $$((
 	d--cQXQ^Q^Q`3vQ`:3diJCJQ`3vwx#>r002JCJJ?@MMRu:u-. 3 	

56eZZ""$<<v6??AD8<=D'',= %$ 4w > %$s*   
F
F
/4F#F>FF
F#c                    U R                   R                  5        nUR                  S5      R                  5       nU Vs/ s H  n[	        U5      PM     snsS S S 5        $ s  snf ! , (       d  f       g = f)NzRSELECT * FROM ingestion_events WHERE job_state = 'pending' ORDER BY created_at ASCr^  rM   r   r   r   s       r   list_pending_events!MemoryService.list_pending_events^  sY    ZZ""$<< tu~~  AD)-.#DI. %$. %$s   $A%A A% A%%
A3c           
         U R                   R                  5        nUR                  SX#U[        5       [        5       U45        S S S 5        g ! , (       d  f       g = f)Nz
                UPDATE ingestion_events
                SET job_state = ?, processor_outcome = ?, error_message = ?, updated_at = ?, processed_at = ?
                WHERE id = ?
                )r_   r   r   r   )rM   event_idstateoutcomeerror_messager   s         r   
mark_eventMemoryService.mark_eventc  sE    ZZ""$LL
 &(HM %$$s   (A
Ac           	         [        5       nU R                  R                  5        nUR                  SXX4U45        S S S 5        U R	                  SS9  g ! , (       d  f       N= f)NzfINSERT OR REPLACE INTO projects (id, name, description, created_at, updated_at) VALUES (?, ?, ?, ?, ?)r
   r]   r   r_   r   r   rd   )rM   rw   namedescriptionr   r   s         r   create_projectMemoryService.create_projectn  sU    hZZ""$LLx;S9 %
 	++!+4 %$   A
A!c           
         [        5       nU R                  R                  5        nUR                  SXX$XU45        S S S 5        U R	                  SS9  g ! , (       d  f       N= f)NzkINSERT OR REPLACE INTO repos (id, project_id, name, path, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)r
   r]   r  )rM   rx   r  rw   pathr   r   s          r   create_repoMemoryService.create_repow  sU    hZZ""$LL}d#; %
 	++!+4 %$r  open   )r?  ru   priorityrw   rx   parent_task_idoriginowner_agentblocked_reasonrequires_human_inputdue_atri   rl   rk   c                  [        5       n0 SU=(       d    [        S5      _S[        _SU_SU_SU_SU_SU_S	U_S
U_SU_SU_SU	_SU
_SU_SU(       a  SOS_SU_SU_UU R                  R	                  U=(       d    0 5      S.EnU R                  R                  5        nUR                  SU5        S S S 5        U R                  SS9  U R                  US   5      $ ! , (       d  f       N1= f)Nrq   r   rs   rk   r{   intentr?  ru   r  rw   rx   r  r  r  r  r  r
   r   r  r~   )r   r   a  
                INSERT INTO tasks (
                    id, schema_version, run_id, title, intent, kind, status, priority, project_id, repo_id,
                    parent_task_id, origin, owner_agent, blocked_reason, requires_human_input, due_at,
                    created_at, updated_at, metadata_json
                ) VALUES (
                    :id, :schema_version, :run_id, :title, :intent, :kind, :status, :priority, :project_id, :repo_id,
                    :parent_task_id, :origin, :owner_agent, :blocked_reason, :requires_human_input, :due_at,
                    :created_at, :updated_at, :metadata_json
                )
                r]   )	r   r   r   r_   r   r   r   rd   get_task)rM   r{   r  r?  ru   r  rw   rx   r  r  r  r  r  r  ri   rl   rk   r   r   r   s                       r   create_taskMemoryService.create_task  sf   ( h
',WV_
n
 f
 U	

 f
 D
 f
 
 *
 w
 n
 f
 ;
 n
 #)=A1
  f!
" ##
$ !ZZ--hn"='
* ZZ""$LL
  % 	++!+4}}VD\**! %$s    C
C,c                    U R                   R                  5        nUR                  SU45      R                  5       nUc  [	        U5      eU R                  U5      sS S S 5        $ ! , (       d  f       g = f)N SELECT * FROM tasks WHERE id = ?)r_   r   r   r   rJ  _row_to_task)rM   rl   r   r   s       r   r  MemoryService.get_task  sZ    ZZ""$,,AG:NWWYC{w''$$S)	 %$$rt  )ru   r  r  rk   r^   c                  S/n/ nUb"  UR                  S5        UR                  U5        Ub"  UR                  S5        UR                  U5        Ub+  UR                  S5        UR                  U(       a  SOS5        Ub"  UR                  S5        UR                  U5        UR                  S5        UR                  U5        U R                  R                  5        nUR                  S	R	                  U5      U5      R                  5       n	U	 V
s/ s H  oR                  U
5      PM     sn
sS S S 5        $ s  sn
f ! , (       d  f       g = f)
NzSELECT * FROM tasks WHERE 1=1r   zAND owner_agent = ?zAND requires_human_input = ?r
   r   zAND run_id = ?z-ORDER BY priority ASC, created_at ASC LIMIT ?r   )r   r_   r   r   r   r'  r  )rM   ru   r  r  rk   r^   r   r   r   r   r   s              r   
list_tasksMemoryService.list_tasks  s    //JJ'(MM&!"JJ,-MM+&+JJ56MM3!;JJ'(MM&!

BCeZZ""$<<v6??AD6:;ds%%c*d; %$; %$s   4D>D9-D>9D>>
E)ru   r  r  r  ri   rk   c               "   U R                  U5      nU=(       d    US   US'   Ub  UOUS   US'   XHS'   Ub  UOUR                  S5      US'   Ub  XXS'   Ub  XhS'   U R                  R                  5        n	U	R	                  SUS   US   US   US   (       a  SOS	UR                  S5      [        5       U R                  R                  US   5      U45        S S S 5        U R                  SS
9  U R                  U5      $ ! , (       d  f       N.= f)Nru   r  r  rk   r  ri   z
                UPDATE tasks
                SET status = ?, owner_agent = ?, blocked_reason = ?, requires_human_input = ?, run_id = ?, updated_at = ?, metadata_json = ?
                WHERE id = ?
                r
   r   r]   )r  r   r_   r   r   r   r   rd   )
rM   rl   ru   r  r  r  ri   rk   r   r   s
             r   update_taskMemoryService.update_task  s#    }}W%14>X-8-Dk$}J]]!/#)#5488H;MX++?'('ZZ""$LL N')*45A1HHX&HJJ$$T*%56	 %$ 	++!+4}}W%%' %$s   5A#D  
D)input_payloadri   c                  [        5       n[        S5      UUSU R                  R                  U=(       d    0 5      S S US UUU R                  R                  U=(       d    0 5      S.nU R                  R	                  5        nUR                  SU5        S S S 5        U R                  SS9  U R                  US   5      $ ! , (       d  f       N1= f)Nr   running)rq   rl   rp   ru   input_payload_jsonresult_summaryr  
started_atcompleted_atr~   r   r   a  
                INSERT INTO task_runs (
                    id, task_id, agent_id, status, input_payload_json, result_summary, error_message,
                    started_at, completed_at, created_at, updated_at, metadata_json
                ) VALUES (
                    :id, :task_id, :agent_id, :status, :input_payload_json, :result_summary, :error_message,
                    :started_at, :completed_at, :created_at, :updated_at, :metadata_json
                )
                r
   r]   rq   )r   r   r_   r   r   r   rd   get_task_run)rM   rl   rp   r  ri   r   r   r   s           r   start_task_runMemoryService.start_task_run	  s     h%. "&**"2"2=3FB"G"! !ZZ--hn"=
 ZZ""$LL  % 	++!+4  .. %$s   B??
Cc                    U R                   R                  5        nUR                  SU45      R                  5       nUc  [	        U5      eU R                  U5      sS S S 5        $ ! , (       d  f       g = f)Nz$SELECT * FROM task_runs WHERE id = ?)r_   r   r   r   rJ  _row_to_task_runrM   rk   r   r   s       r   r  MemoryService.get_task_run0  sZ    ZZ""$,,EyQZZ\C{v&&((-	 %$$rt  )r  r  c          
         [        5       nU R                  R                  5        nUR                  SX#XEXQ45        S S S 5        U R	                  SS9  U R                  U5      $ ! , (       d  f       N.= f)Nz
                UPDATE task_runs
                SET status = ?, result_summary = ?, error_message = ?, updated_at = ?, completed_at = ?
                WHERE id = ?
                r
   r]   )r   r_   r   r   rd   r  )rM   rk   ru   r  r  r   r   s          r   finish_task_runMemoryService.finish_task_run7  sl     hZZ""$LL
 SI % 	++!+4  (( %$s   A##
A1)rl   ru   r^   c                  S/n/ nUb"  UR                  S5        UR                  U5        Ub"  UR                  S5        UR                  U5        UR                  S5        UR                  U5        U R                  R                  5        nUR                  SR	                  U5      U5      R                  5       nU Vs/ s H  oR                  U5      PM     snsS S S 5        $ s  snf ! , (       d  f       g = f)Nz!SELECT * FROM task_runs WHERE 1=1AND task_id = ?r    ORDER BY created_at DESC LIMIT ?r   )r   r_   r   r   r   r'  r  )	rM   rl   ru   r^   r   r   r   r   r   s	            r   list_task_runsMemoryService.list_task_runsL  s    23JJ()MM'"JJ'(MM&!

56eZZ""$<<v6??AD:>?$3))#.$? %$? %$s   4C+ C&C+&C++
C9md)fmtru   r   ri   artifact_idc       	        l   [        5       n
U	=(       d    [        S5      UUUUUUUU
U
U R                  R                  U=(       d    0 5      S.nU R                  R	                  5        nUR                  SU5        S S S 5        U R                  SS9  U R                  US   5      $ ! , (       d  f       N1= f)Nart)rq   rl   artifact_typer{   r2   formatru   r   r~   r   r   au  
                INSERT INTO artifacts (
                    id, task_id, artifact_type, title, content, format, status, source_ref, created_at, updated_at, metadata_json
                ) VALUES (
                    :id, :task_id, :artifact_type, :title, :content, :format, :status, :source_ref, :created_at, :updated_at, :metadata_json
                )
                r
   r]   rq   )r   r   r_   r   r   r   rd   get_artifact)rM   rl   r  r{   r2   r  ru   r   ri   r  r   r   r   s                r   create_artifactMemoryService.create_artifact[  s     h/*$!ZZ--hn"=
 ZZ""$LL 	 % 	++!+4  .. %$s   'B%%
B3c                    U R                   R                  5        nUR                  SU45      R                  5       nUc  [	        U5      eU R                  U5      sS S S 5        $ ! , (       d  f       g = f)Nz$SELECT * FROM artifacts WHERE id = ?)r_   r   r   r   rJ  _row_to_artifact)rM   r  r   r   s       r   r  MemoryService.get_artifact  sZ    ZZ""$,,E~V__aC{{++((-	 %$$rt  rl   r^   c                  S/n/ nUb"  UR                  S5        UR                  U5        UR                  S5        UR                  U5        U R                  R                  5        nUR                  SR	                  U5      U5      R                  5       nU Vs/ s H  opR                  U5      PM     snsS S S 5        $ s  snf ! , (       d  f       g = f)Nz!SELECT * FROM artifacts WHERE 1=1r  r  r   )r   r_   r   r   r   r'  r  )rM   rl   r^   r   r   r   r   r   s           r   list_artifactsMemoryService.list_artifacts  s    23JJ()MM'"

56eZZ""$<<v6??AD:>?$3))#.$? %$? %$s   '4CC5CC
C)r  c                   U R                  USS9nU Vs/ s H  o3S   S;   d  M  UPM     snS S nU R                  SUSS9nU R                  SS9nU R                  SS9nUUUUS	.$ s  snf )
Nru  )r  r^   ru   >   r  draftin_progress   blocked)ru   r  r^   r]   )active_tasksblocked_tasksrecent_runsrecent_artifacts)r  r  r  )rM   r  r  r   r  r  r  s          r   dashboard_snapshot MemoryService.dashboard_snapshot  s    ;bI)5lhKk9klmpnpqykY[\)))3..R.8(*& 0	
 	
	 ms
   A'A'c                \   U R                  U5      nU R                  R                  5        nUR                  SU45      R	                  5       nS S S 5        UW Vs/ s H  oPR                  U5      PM     snU R                  USS9U R                  USS9S.$ ! , (       d  f       NP= fs  snf )NzRSELECT * FROM tasks WHERE parent_task_id = ? ORDER BY priority ASC, created_at ASCd   r  )r   childrenrunsr]  )r  r_   r   r   r'  r  r  r  )rM   rl   r   r   
child_rowsr   s         r   task_bundleMemoryService.task_bundle  s    }}W%ZZ""$d
 hj  % ;EF:C**3/:F''s'C,,WC,H	
 	
 %$ Gs   "BB)
B&c           	        U R                   R                  5        nU R                  US5      nU R                  US5      nUR                  S[        45      R                  5       S   nUR                  S[        45      R                  5       S   nUR                  S5      R                  5       S   nUR                  S5      R                  5       S   nU R                  US5      nS S S 5        [        WWWWWWWS	.$ ! , (       d  f       N= f)
N	approvalshandoffsa"  
                SELECT COUNT(*) AS count
                FROM memories
                WHERE schema_version != ?
                   OR json_extract(metadata_json, '$.legacy_kind') IS NOT NULL
                   OR json_extract(metadata_json, '$.legacy_system') IS NOT NULL
                counta  
                SELECT COUNT(*) AS count
                FROM tasks
                WHERE schema_version != ?
                   OR json_extract(metadata_json, '$.legacy_kind') IS NOT NULL
                   OR json_extract(metadata_json, '$.legacy_system') IS NOT NULL
                z&SELECT COUNT(*) AS count FROM memoriesz#SELECT COUNT(*) AS count FROM tasksrX  )rs   rT  r[  r  r  rX  legacy_memory_rowslegacy_task_rows)r_   r   _count_if_table_existsr   r   r   )	rM   r   r  r  r  r  rT  r[  rX  s	            r   audit_v2MemoryService.audit_v2  s   ZZ""$33D+FI224DH!%  !	" hj	""  $||  !	  hj	 " ||$LMVVXY`aHLL!FGPPRSZ[E#::4AST3 %6 - "  0"4 0	
 		
5 %$s   CC==
Dc                   U R                  5       nSSSSS.nU R                  R                  5        nUR                  S5      R	                  5       nU Hv  nU R                  [        U5      5      nUc  M"  UR                  SUS   US   US   US   US	   US
   US   US   US   US   [        5       US   45        US==   S-  ss'   Mx     UR                  S5      R	                  5       nU HZ  nU R                  [        U5      5      nUc  M"  UR                  SUS   US	   US   [        5       US   45        US==   S-  ss'   M\     U R                  US5      (       Ga  UR                  S5      R	                  5        GHg  n[        U5      nUR                  SUS
   45      R                  5       n	U	c  M8  U R                  U	5      n
[        U
R                  S0 5      5      nUS   US   U R                  R                  US   5      =(       d    0 US   US   US   US   S .US!'   UR                  S"U R                  R                  U5      [        5       US
   45        UR                  S#[        S$5      US
   S%S&US    3[         R                  " US!   S'S(9S)US   S*:w  a  S+OS,S-[        5       [        5       U R                  R                  0 5      45        US.==   S-  ss'   GMj     UR                  S/5        U R                  US05      (       Ga  UR                  S15      R	                  5        H  n[        U5      nU R                  R                  US   5      =(       d    0 nUR                  S#[        S$5      US
   S2S3US4    S5US6    3[         R                  " US4   US6   US7   US   UUS8   US9   US:   S;.S'S(9S)S,S-[        5       [        5       U R                  R                  0 5      45        US<==   S-  ss'   M     UR                  S=5        S S S 5        U R                  5       nS>XUS?.$ ! , (       d  f       N$= f)@Nr   )rT  r[  approval_artifactshandoff_artifactszSELECT * FROM memoriesa$  
                    UPDATE memories
                    SET schema_version = ?, type = ?, subtype = ?, origin_agent = ?, run_id = ?, task_id = ?,
                        url = ?, domain = ?, summary = ?, metadata_json = ?, updated_at = ?
                    WHERE id = ?
                    rs   rt   rj   ro   rk   rl   rm   rn   r|   r   rq   rT  r
   zSELECT * FROM tasksz
                    UPDATE tasks
                    SET schema_version = ?, run_id = ?, metadata_json = ?, updated_at = ?
                    WHERE id = ?
                    r[  r  zSELECT * FROM approvalsr  ri   r?  
risk_levelpayload_jsonru   requested_atresolved_atresolution_note)r?  r  r   ru   r  r  r  approvalz
                        UPDATE tasks
                        SET metadata_json = ?, updated_at = ?
                        WHERE id = ?
                        a  
                        INSERT INTO artifacts (
                            id, task_id, artifact_type, title, content, format, status, source_ref, created_at, updated_at, metadata_json
                        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                        r  approval_resolutionz	Approval T)	sort_keysjsonpendingr   rv   zmigration:v2r  zDROP TABLE approvalsr  zSELECT * FROM handoffsdelegation_notezHandoff 
from_agentz -> to_agentr   r  r  r  )r  r  r   ru   r   r  r  r  r  zDROP TABLE handoffsok)ru   beforeaftermigrated)r  r_   r   r   r'  _migrate_memory_rowr   r   _migrate_task_row_table_existsr   r  r   rI  r   r   r  )rM   r  r  r   memory_rowsr   r   	task_rowsr  task_rowr   ri   handoffr   r  s                  r   rb   MemoryService.migrate_v2  s    !AQ]^_ZZ""$,,'?@IIKK"11$s)<> /0vy)~.x(y)ux(y)/t, $)$5 #6 %:;DDFI //S	:>
 ,-vh/?AXZ`Zbdjkodpq !Q&! ! !!$44<<(ABKKMC#CyH#||,NQYZcQdPfgpprH' ,,X6D#DHHZ$<=H ( 0&.|&<#'::#3#3H^4L#M#SQS"*8"4(0(@'/'>+34E+F,HZ( LL
 ))(3VXx	?RS LL $EN$Y/1'(8'9: JJx
';tL"*28*<	*IJx*"H"H JJ,,R0( 12a72Y NZ 34!!$
33<<(@AJJLC"3iG"jj..w~/FGM2GLL $EN#I.-&w|'<&=T'*BUAVW JJ29,2G07
0C.5h.?.5h.?/66=>N6O5<_5M4;N4K	!" +/ #$*"H"H JJ,,R0/@ 01Q61G MH 23 %@ &hWWC %$s   O,P<<
Q
c                   [        5       n[        S5      UUR                  S5      =(       d    UUUU R                  R	                  U5      US.n[        S5      UUS   USS SS UUS S.n	U R                  R                  5        n
U
R                  S	U5        U
R                  S
U	5        S S S 5        U R                  SS9  XS.$ ! , (       d  f       N!= f)Nsrcr{   )rq   ry   r{   r2   r   r   r~   ingrq   r  r   )rq   r   	source_idrequested_scope	job_stateprocessor_outcomeretry_countr  r~   r   processed_atz
                INSERT INTO sources (id, source_kind, title, content, source_ref, metadata_json, created_at)
                VALUES (:id, :source_kind, :title, :content, :source_ref, :metadata_json, :created_at)
                a  
                INSERT INTO ingestion_events (
                    id, trigger_type, source_id, requested_scope, job_state, processor_outcome,
                    retry_count, error_message, created_at, updated_at, processed_at
                ) VALUES (
                    :id, :trigger_type, :source_id, :requested_scope, :job_state, :processor_outcome,
                    :retry_count, :error_message, :created_at, :updated_at, :processed_at
                )
                r
   r]   )rL  event)r   r   r   r_   r   r   r   rd   )rM   r   ry   r   rI   r2   ri   r   rL  r  r   s              r   r   MemoryService._capture_source^  s     h%.&\\'*8j$!ZZ--h7
 %.($"!%! 
 ZZ""$LL  LL  %( 	++!+4 11+ %$s   %C
Cc                   U R                   (       a  g U R                  SS9nU(       d  g SU l          SSKJn  U" U 5      R	                  US9   SU l         g ! [
         a
     SU l         g f = f! SU l         f = f)Nr
   r]   T)MemoryEngineF)r`   list_due_maintenance_jobsenginer  run_due_maintenance	Exception)rM   r^   due_jobsr  s       r   rd   ,MemoryService._run_opportunistic_maintenance  s~    **111:*.'	4,222? /4D+  	.3D+	 /4D+s#   A 
A* A- )A**A- -	A6c                    / n1 SknUR                  5        H5  u  pVXT;  d  Uc  M  UR                  SU S35        UR                  U5        M7     U$ )N>	   rm   rt   rn   rk   rx   rj   rl   rw   ro   zAND z = ?)rw  r   )rM   r   r   r   allowedr   r!   s          r   r    MemoryService._memory_filter_sql  sS    t!--/JC!U]JJcU$'(MM% 	 *
 r   c                   ^^ / SQnU Vs/ s H  nTR                  U5      c  M  UPM     nnU(       d  g[        UU4S jU 5       5      nU[        U5      -  $ s  snf )N)	rw   rx   rt   rj   rk   rl   ro   rm   rn   r   c              3  \   >#    U  H!  nTR                  U5      TU   :X  d  M  S v   M#     g7fr
   Nrh  )r   r   r   r;   s     r   r   -MemoryService._facet_score.<locals>.<genexpr>  s&     N7Cfjjo.Maa7s   ,	,)r   sumr0   )rM   r;   r   trackedr   appliedmatcheds    ``    r   r   MemoryService._facet_score  sR    t")J'3W[[-=3'JN7NNW%%	 Ks
   AAc                   U R                   R                  UR                  S5      5      =(       d    0 nUR                  S5      [        :X  a-  UR                  S5      (       d  UR                  S5      (       d  g U R	                  U5      nUR                  S5      =(       dA    UR                  S5      =(       d)    UR                  S5      =(       d    UR                  S5      nUR                  S5      =(       dA    UR                  S5      =(       d)    UR                  S5      =(       d    U R                  X5      nUR                  S	5      =(       d    UR                  S	5      nUR                  S
5      =(       dA    UR                  S
5      =(       d)    UR                  S5      =(       d    U R                  X5      nUR                  S5      =(       d6    UR                  S5      =(       d    U(       a  [        U5      R                  OS nUR                  5        V	V
s0 s H  u  pU	S;  d  M  X_M     nn	n
US:X  a  UR                  S5      =(       d8    [        US   S5      =(       d"    US   R                  S5      R                  5       US'   UR                  S5      =(       d    [        US   S5      US'   UR                  S5      =(       d    [        US   S5      US'   UR                  S5      =(       d    [        US   S5      =(       d    US   US'   [        US'   X;S'   US   nUS:X  a  SnOUS:X  a  S nUS!   [        UUUUUUUUR                  SUS   5      U R                   R                  U5      S".$ s  sn
n	f )#Nr   rs   legacy_kindlegacy_systemro   rp   rk   legacy_run_idrl   rm   
source_urlrn   >
   rm   rn   rk   schemarl   r(  r%  record_kindr'  r&  research_rungoalr2   Goalr{   zResearch run: rI   ScopeassumptionsAssumptionsr|   Summaryr)  rj   rt   router_handoffr   research_sourcer   rq   )rq   rs   rt   rj   ro   rk   rl   rm   rn   r|   r   )r_   rI  r   r   _memory_subtype_infer_run_id
_infer_urlr	   r   rw  r5   removeprefixr1   r   )rM   r   ri   rj   ro   rk   rl   rm   rn   r   r!   cleanrecord_types                r   r  !MemoryService._migrate_memory_row  s0   ::##CGGO$<=C77#$6x||M?Z?Zckcocop  dA  dA&&x0ww~.  G(,,~2N  GRZR^R^_nRo  Gsvszsz  |F  tG"  Bhll8&<  B_@]  Baeasastw  bB'')$?Y(?ggenrU 3rx||L7QrUYUdUdehUr"ghll8&<gY\#AUAUbf.6nn.>  M.>
#  NL  CL.>  Mn$!IIf-  LS^V1T  LX[\cXdXqXq  sC  YD  YJ  YJ  YLE&M"YYw/W;s9~w3WE'N#(99]#;#i{3y>[h?iE- $yy3o{3y>S\7]oadenaoE)(h"i&k&&#K))$Kd),(yyC	N;!ZZ--e4
 	
 Ms    N 0N c                :   U R                   R                  UR                  S5      5      =(       d    0 nUR                  S5      [        :X  a-  UR                  S5      (       d  UR                  S5      (       d  g UR                  S5      =(       d)    UR                  S5      =(       d    UR                  S5      nUR	                  5        VVs0 s H  u  pEUS;  d  M  XE_M     nnn[        US'   US	   [        UU R                   R                  U5      S
.$ s  snnf )Nr   rs   r%  r&  rk   r'  >   r%  r'  r&  r)  rq   )rq   rs   rk   r   )r_   rI  r   r   rw  r   )rM   r   ri   rk   r   r!   r8  s          r   r  MemoryService._migrate_task_row  s    ::##CGGO$<=C77#$6x||M?Z?Zckcocop  dA  dA"]hll8&<]_@].6nn.>.>
#M~B~.>(hd),!ZZ--e4	
 	
 @s   DDc                   SSSS SS SSSSS	S
SSS/ SQS.
S.SSSS SS SSSSS	S
SSS/ SQS.
S.SSSS S S SSSSS	S
SSS/ SQS.
S./nU R                   R                  5        nUR                  SS5      R                  5       nU(       a  UR                  SS[	        5       S45        U H  nUR                  SUS   45      R                  5       nU(       a  M0  [	        5       nU R                  XdS   US   US    US!   5      nUR                  S"US   US#   US   US   US    US!   US S S S$U R                   R                  US%   5      UU45        M     S S S 5        g ! , (       d  f       g = f)&Njob_consolidation_daily_10consolidationdailyz10:00daily_10r   r
  r  r  r  r  Fr  r  )
moder  r	  r  r  r  r  r  r  r  )rq   job_typecadenceinterval_minuteswindow_start
window_endri   job_consolidation_daily_15z15:00daily_15job_consolidation_weeklyweeklyi   Tz,SELECT id FROM maintenance_jobs WHERE id = ?)job_consolidation_dailyz
                    UPDATE maintenance_jobs
                    SET enabled = 0, last_summary = ?, updated_at = ?
                    WHERE id = ?
                    z+deprecated: split into 10:00 and 15:00 jobsrL  rq   rD  rE  rF  rG  ag  
                    INSERT INTO maintenance_jobs (
                        id, job_type, cadence, interval_minutes, window_start, window_end, next_due_at,
                        last_run_at, last_status, last_summary, enabled, metadata_json, created_at, updated_at
                    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                    rC  r
   ri   )r_   r   r   r   r   _compute_next_duer   )rM   defaultsr   legacyjobr   r   next_dues           r   rc   "MemoryService._ensure_default_jobs  s    3+"$( '"&*+&)-0,0*-*.#($.#J* 3+"$( '"&*+&)-0,0*-*.#($.#J* 1+#$( $"$*+&)-0,0*-*.#'$.#JS=
| ZZ""$\\"PRnoxxzF
 CFHNgh  ll#QTWX\T]S_`iikh11#9~sK]G^`cdr`sux  zF  vG  H D	JI./N+L) 

((Z9   %$$s   C3E
E)c                    U R                   R                  5        nUR                  S5      R                  5       nU Vs/ s H  o0R	                  U5      PM     snsS S S 5        $ s  snf ! , (       d  f       g = f)Nz7SELECT * FROM maintenance_jobs ORDER BY next_due_at ASC)r_   r   r   r'  _row_to_maintenance_jobrz  s       r   list_maintenance_jobs#MemoryService.list_maintenance_jobsM  s[    ZZ""$<< YZcceDAEF#005F %$F %$s   $A*A%A*%A**
A8)r   r^   c               X   U=(       d
    [        5       nSnU/nUb  US-  nUR                  U5        U R                  R                  5        nUR	                  X45      R                  5       nU Vs/ s H  opR                  U5      PM     snsS S S 5        $ s  snf ! , (       d  f       g = f)Nz^SELECT * FROM maintenance_jobs WHERE enabled = 1 AND next_due_at <= ? ORDER BY next_due_at ASCz LIMIT ?)r   r   r_   r   r   r'  rT  )rM   r   r^   r   r   r   r   r   s           r   r  'MemoryService.list_due_maintenance_jobsR  s    oVXn E:CMM% ZZ""$<<,557DAEF#005F %$F %$s   $B0B
BB
B)c                    U R                   R                  5        nUR                  SU45      R                  5       nUc  [	        U5      eU R                  U5      sS S S 5        $ ! , (       d  f       g = f)Nz+SELECT * FROM maintenance_jobs WHERE id = ?)r_   r   r   r   rJ  rT  )rM   job_idr   r   s       r   get_maintenance_job!MemoryService.get_maintenance_job]  Z    ZZ""$,,LviXaacC{v&&//4	 %$$rt  )
rD  rE  rF  rG  next_due_atlast_run_atlast_statuslast_summaryenabledri   c       
           U R                  U5      nUb  X,S'   Ub  X<S'   Ub  XLS'   Ub  X\S'   Ub  XlS'   Ub  X|S'   Ub  XS'   U	b  XS'   U
b  XS	'   Ub  XS
'   U R                  R                  5        nUR                  SUS   UR	                  S5      UR	                  S5      UR	                  S5      US   UR	                  S5      UR	                  S5      UR	                  S5      UR	                  S	5      (       a  SOSU R                  R                  UR	                  S
5      =(       d    0 5      [        5       U45        S S S 5        U R                  U5      $ ! , (       d  f       N= f)NrD  rE  rF  rG  r^  r_  r`  ra  rb  ri   a7  
                UPDATE maintenance_jobs
                SET cadence = ?, interval_minutes = ?, window_start = ?, window_end = ?,
                    next_due_at = ?, last_run_at = ?, last_status = ?, last_summary = ?, enabled = ?, metadata_json = ?, updated_at = ?
                WHERE id = ?
                r
   r   )r[  r_   r   r   r   r   r   )rM   rZ  rD  rE  rF  rG  r^  r_  r`  ra  rb  ri   rP  r   s                 r   update_maintenance_job$MemoryService.update_maintenance_jobd  s|    &&v.$	N'&6"##".! *"!,"!,"!,#".$	N&
OZZ""$LL 	NGG./GGN+GGL)&GGM*GGM*GGN+++AJJ$$SWWZ%8%>B?H %. ''/// %$s   2CE
E))r   c               N    U R                  U=(       d
    [        5       UUUU5      $ r   )rM  r   )rM   r   rD  rE  rF  rG  s         r   compute_next_dueMemoryService.compute_next_due  s,     %%O68
 	
r   c                   [        S5      n[        5       nU R                  R                  5        nUR	                  SX!SUS S U R                  R                  0 5      S 45        S S S 5        U R                  U5      $ ! , (       d  f       N= f)Nmrunz
                INSERT INTO maintenance_runs (id, job_id, status, started_at, completed_at, summary, stats_json, error_message)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?)
                r  )r   r   r_   r   r   r   get_maintenance_run)rM   rZ  rk   r   r   s        r   create_maintenance_run$MemoryService.create_maintenance_run  sz    hZZ""$LL CtTZZ=M=Mb=QSWX % ''// %$s   3A<<
B
)r|   r-  r  c                  [        5       nU R                  R                  5        nUR                  SX&X0R                  R	                  U=(       d    0 5      XQ45        S S S 5        U R                  U5      $ ! , (       d  f       N= f)Nz
                UPDATE maintenance_runs
                SET status = ?, completed_at = ?, summary = ?, stats_json = ?, error_message = ?
                WHERE id = ?
                )r   r_   r   r   r   rk  )rM   rk   ru   r|   r-  r  r   r   s           r   finish_maintenance_run$MemoryService.finish_maintenance_run  sn     hZZ""$LL
 gzz'7'7'Dm\ % ''// %$s   8A66
Bc                    U R                   R                  5        nUR                  SU45      R                  5       nUc  [	        U5      eU R                  U5      sS S S 5        $ ! , (       d  f       g = f)Nz+SELECT * FROM maintenance_runs WHERE id = ?)r_   r   r   r   rJ  _row_to_maintenance_runr  s       r   rk  !MemoryService.get_maintenance_run  r]  rt  r  )rZ  r^   c               \   Sn/ nUb  US-  nUR                  U5        US-  nUR                  U5        U R                  R                  5        nUR                  X45      R	                  5       nU Vs/ s H  opR                  U5      PM     snsS S S 5        $ s  snf ! , (       d  f       g = f)Nz(SELECT * FROM maintenance_runs WHERE 1=1z AND job_id = ?z! ORDER BY started_at DESC LIMIT ?)r   r_   r   r   r'  rr  )rM   rZ  r^   r   r   r   r   r   s           r   list_maintenance_runs#MemoryService.list_maintenance_runs  s    8$$CMM&!22eZZ""$<<,557DAEF#005F %$F %$s   $B2BBB
B+c                    UR                  S5      =(       d)    UR                  S5      =(       d    UR                  S5      nSSSSSSSSS	S
S.
nUR                  X"5      $ )Nr*  r%  rj   r+  research_stepr3  research_claimresearch_artifactleisure_itemr2  )
r+  rx  rL  r3  claimry  r   rz  r{  r2  rh  )rM   ri   r*  mappings       r   r4  MemoryService._memory_subtype  sf    ll=1kX\\-5PkT\T`T`ajTk*,'0%.+!4*.
 {{;44r   c                    UR                  S5      =(       d    SnUR                  S5      (       a  UR                  SS5      S   $ US:X  a  US   $ g )	Nr   r-   zpersonal-agent:run:r,   r
   r+  rq   )r   r/   rsplit)rM   r   rj   r   s       r   r5  MemoryService._infer_run_id  sT    WW\*0b
  !677$$S!,R00n$t9r   c                    US;   a>  UR                  S5      n[        U[        5      (       a  UR                  S5      (       a  U$ g )N>   ry  r3  rz  rJ   )zhttp://zhttps://)r   r   r>   r/   )rM   r   rj   rJ   s       r   r6  MemoryService._infer_url  s@    PP77>2L,,,1H1HI`1a1a##r   c                t    UR                  SUS   45        UR                  SUS   US   US   US   45        g )Nz,DELETE FROM memories_fts WHERE memory_id = ?rq   zQINSERT INTO memories_fts (memory_id, title, summary, content) VALUES (?, ?, ?, ?)r{   r|   r2   )r   )rM   r   r   s      r   r   MemoryService._upsert_fts  sD    CfTl_U_D\6'?F9,=vi?PQ	
r   c                    [        U5      nU R                  R                  UR                  S5      5      =(       d    0 US'   U R	                  UR                  S5      5      US'   U$ )Nr   ri   r   r   )r   r_   rI  pop_decode_embedding)rM   r   r;   s      r   r   MemoryService._row_to_memory  sV    c!ZZ--fjj.IJPbz"44VZZ@P5QR{r   c                    [        U5      nU R                  R                  UR                  S5      5      =(       d    0 US'   [	        US   5      US'   U$ )Nr   ri   r  r   r_   rI  r  r&  )rM   r   r   s      r   r  MemoryService._row_to_task  sM    Cy::++DHH_,EFL"Z'+D1G,H'I#$r   c                    [        U5      nU R                  R                  UR                  S5      5      =(       d    0 US'   U R                  R                  UR                  S5      5      =(       d    0 US'   U$ )Nr  r  r   ri   r   r_   rI  r  rM   r   r   s      r   r  MemoryService._row_to_task_run  s_    3i#zz//8L0MNTRTO****377?+CDJJ
r   c                    [        U5      nU R                  R                  UR                  S5      5      =(       d    0 US'   U$ )Nr   ri   r  )rM   r   r   s      r   r  MemoryService._row_to_artifact  s8    9#zz//_0MNTRTr   c                    [        U5      nU R                  R                  UR                  S5      5      =(       d    0 US'   [	        US   5      US'   U$ )Nr   ri   rb  r  )rM   r   rP  s      r   rT  %MemoryService._row_to_maintenance_job$  sH    3i****377?+CDJJc)n-I
r   c                    [        U5      nU R                  R                  UR                  S5      5      =(       d    0 US'   U$ )N
stats_jsonr-  r  r  s      r   rr  %MemoryService._row_to_maintenance_run*  s6    3izz''(=>D"G
r   c                x    SR                  UR                  5       5      n[        U5      U:  a  US US-
   S-   $ U$ )Nr   r
   u   …)r   r    r0   )rM   r2   max_lencompacts       r   r   MemoryService._make_summary/  s<    ((7==?+14W1Gw}1%-TWTr   c                6    Uc  g [         R                  " U5      $ r   )r  r   rM   r   s     r   r   MemoryService._encode_embedding3  s    zz)$$r   c                P    U(       d  g [        [        R                  " U5      5      $ r   )rj  r  rI  r  s     r   r  MemoryService._decode_embedding8  s    DJJy)**r   c                Z   ^ U(       d  g[        U4S jU 5       5      nU[        U5      -  $ )Nr   c              3  6   >#    U  H  oT;   d  M
  S v   M     g7fr  r   )r   r   r   s     r   r   /MemoryService._lexical_score.<locals>.<genexpr>@  s     DKD83CaaKs   		)r  r0   )rM   r   r   matchess     ` r   r   MemoryService._lexical_score=  s)    DKDD[)))r   c                T   S/U-  n[        U5      R                  5        H>  n[        UR                  S5      5       H  u  pVX5U-  ==   [	        U5      -  ss'   M     M@     [
        R                  " [        S U 5       5      5      nUS:X  a  U$ U Vs/ s H  oU-  PM	     sn$ s  snf )Nr   zutf-8c              3  *   #    U  H	  oU-  v   M     g 7fr   r   )r   r!   s     r   r   0MemoryService._text_embedding.<locals>.<genexpr>H  s     ?uU]s   r   )r"   r    	enumerateencoder<   mathsqrtr  )	rM   r)   
dimensionsvectortokenidxcharnormr!   s	            r   r   MemoryService._text_embeddingC  s    ##D)//1E&u||G'<=	Z'(E$K7( > 2 yy???@19M*01&&111s   B%c                z    U(       a  Uc  g[        S [        X5       5       5      n[        S[        SU5      5      $ )Nr   c              3  .   #    U  H  u  pX-  v   M     g 7fr   r   )r   abs      r   r   0MemoryService._semantic_score.<locals>.<genexpr>P  s     Q*P$!*Ps   r}   )r  zipmaxmin)rM   r   memory_embedding	numerators       r   r   MemoryService._semantic_scoreM  s7    "2":Q#o*PQQ	3C+,,r   c                L    UR                  SU45      R                  5       nUS L$ )Nz@SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?)r   r   )rM   r   ra  r   s       r   r  MemoryService._table_existsS  s*    ll]`e_ghqqs$r   c                z    U R                  X5      (       d  gUR                  SU 35      R                  5       S   $ )Nr   zSELECT COUNT(*) AS count FROM r  )r  r   r   )rM   r   ra  s      r   r  $MemoryService._count_if_table_existsW  s<    !!$..||<UGDENNPQXYYr   c                   [         R                  " U5      nUS:X  a!  U(       a  U[        US9-   R                  5       $ US:X  a  U[        SS9-   nOU[        SS9-   nU(       a$  U R	                  U5      u  pUR                  XSSS9nU(       a+  U R	                  U5      u  pUR                  XSSS9nX|:  a  UnUR                  5       $ )	Ninterval)minutesrK  r  r  r
   r   )hourminutesecondmicrosecond)r   fromisoformatr   r   _parse_hhmmreplace)rM   r   rD  rE  rF  rG  basetargetr  r  end_hour
end_minuteends                r   rM  MemoryService._compute_next_due\  s     %%c*j %59-=>>IIKKhI1--FI1--F++L9LD^^QTU^VF#'#3#3J#? H..h!YZ.[C|!!r   c                |    UR                  S5      n[        U5      S:w  a  g[        US   5      [        US   5      4$ )Nr,      )r   r   r   r
   )r    r0   r%  )rM   r!   partss      r   r  MemoryService._parse_hhmmu  s9    C u:?E!Hs58}--r   c                    UR                  S[        S5      X#U[        5       U R                  R	                  SU05      45        g )Nz
            INSERT INTO memory_links (id, from_memory_id, to_memory_id, relation, created_at, metadata_json)
            VALUES (?, ?, ?, ?, ?, ?)
            r   r   r   r   r   r_   r   )rM   r   from_idto_idr   r   s         r   r(  MemoryService._link_memories{  s?     U^WXvxAQAQS[]cRdAef	
r   c                    UR                  S[        S5      X#U[        5       U R                  R	                  0 5      45        g )Nz
            INSERT INTO memory_conflicts (id, memory_id, conflicting_memory_id, reason, created_at, metadata_json)
            VALUES (?, ?, ?, ?, ?, ?)
            mcfr  )rM   r   r   conflicting_idr   s        r   r+  MemoryService._record_conflict  s9     U^Y$**JZJZ[]J^_	
r   c                j   1 SknUR                  S5      U;  d  UR                  S5      U;  a  g1 Skn[        [        US   5      R                  5       5      n[        [        US   5      R                  5       5      n[	        XE-  5      n[	        XF-  5      n[        XV-  5      n	U	S:  =(       a    Xx:g  $ )N>   r   r   r   rt   F>   nonotsinnevernuncar2   r  )r   setr"   r    r&  r0   )
rM   leftrightallowed_types	negationsleft_tokensright_tokensleft_neg	right_negoverlaps
             r   r*  MemoryService._conflict_signal  s    :88F=0EIIf4E]4Z:	.i9??AB>%	*:;AACD	/012	k01!|5 55r   c          	         US:w  a  g SUS    SUS    S3n [         R                  " UUSSSSS	9nUR                  S
:w  a  g UR                  R	                  5       nU=(       d    S $ ! [
         a     g f = f)Nr  zzSummarize and merge the two memory notes into one concise statement. Preserve key facts and avoid speculation.

Memory A:
r2   z

Memory B:

T<   F)inputr)   capture_outputtimeoutcheckr   )
subprocessr   
returncodestdoutr1   r  )rM   r  r  r  r  promptresultoutputs           r   r)  !MemoryService._llm_summarize_pair  s     z!y/*/%	:J9K2O 		^^#F   A%]]((*F>T! 		s   )A' $A' '
A43A4)r`   r_   )re   r>   rQ   None)r   r:   rQ   r:   )
r   r>   rI   r>   r2   r>   ri   r   rQ   r:   )manual_import)r   r>   rI   r>   r2   r>   r   r>   ri   r   rQ   r:   )NNr\   F)r   r>   r   zlist[str] | Noner   dict[str, Any] | Noner^   r%  r   r&  rQ   r:   )NNNN)
r   
str | Noner   r  r   r  r   r  rQ   r:   )r   	list[str]rQ   r:   )r,  r:   rQ   r:   )NN)
r{   r>   r2   r>   rJ   r  r   r  rQ   r:   )rK  r>   rQ   r:   rP   )r   r:   rQ   r   )r   r>   rQ   r:   ) ru   r  rI   r  r   r  rj   r  rw   r  rx   r  r   r  rJ   r  rk   r  rl   r  ro   r  rm   r  rn   r  ri   r  r^   r%  rQ   list[dict[str, Any]])rQ   r  )
r~  r>   r  r>   r  r  r  r  rQ   r   r   )rw   r>   r  r>   r  r  rQ   r   )
rx   r>   r  r>   rw   r  r  r  rQ   r   )"r{   r>   r  r>   r?  r>   ru   r>   r  r%  rw   r  rx   r  r  r  r  r  r  r  r  r  r  r&  r  r  ri   r  rl   r  rk   r  rQ   r:   )rl   r>   rQ   r:   )ru   r  r  r  r  bool | Nonerk   r  r^   r%  rQ   r  )rl   r>   ru   r  r  r  r  r  r  r  ri   r  rk   r  rQ   r:   )
rl   r>   rp   r>   r  r  ri   r  rQ   r:   )rk   r>   rQ   r:   )
rk   r>   ru   r>   r  r  r  r  rQ   r:   )rl   r  ru   r  r^   r%  rQ   r  )rl   r>   r  r>   r{   r>   r2   r>   r  r>   ru   r>   r   r  ri   r  r  r  rQ   r:   )r  r>   rQ   r:   )rl   r  r^   r%  rQ   r  )r  r  rQ   r:   )r   r>   ry   r>   r   r>   rI   r>   r2   r>   ri   r:   rQ   r:   )r^   r%  rQ   r   )r   r  r   r:   rQ   z	list[Any])r;   r:   r   r:   rQ   r<   )r   r:   rQ   r  )rQ   r   )r   r  r^   
int | NonerQ   r  )rZ  r>   rQ   r:   )rZ  r>   rD  r  rE  r  rF  r  rG  r  r^  r  r_  r  r`  r  ra  r  rb  r  ri   r  rQ   r:   )r   r  rD  r>   rE  r  rF  r  rG  r  rQ   r>   )rk   r>   ru   r>   r|   r  r-  r  r  r  rQ   r:   )rZ  r  r^   r%  rQ   r  )ri   r:   rQ   r  )r   r:   rj   r  rQ   r  )r   r   r   r:   rQ   r   )r   r   rQ   r:   )   )r2   r>   r  r%  rQ   r>   )r   list[float] | NonerQ   r  )r   r  rQ   r	  )r   r  r   r>   rQ   r<   )r   )r)   r>   r  r%  rQ   list[float])r   r
  r  r	  rQ   r<   )r   r   ra  r>   rQ   r&  )r   r   ra  r>   rQ   r%  )r   r>   rD  r>   rE  r  rF  r  rG  r  rQ   r>   )r!   r>   rQ   ztuple[int, int])r   r   r  r>   r  r>   r   r>   r   r>   rQ   r   )
r   r   r   r>   r  r>   r   r>   rQ   r   )r  r:   r  r:   rQ   r&  )
r  r:   r  r:   r  r>   r  r  rQ   r  )OrR   rS   rT   rU   rf   r   r   r   r   r   r   r  r<  rA  rM  rb  rp  r   r   r{  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  rb   r   rd   r   r   r  r  rc   rU  r  r[  rd  rg  rl  ro  rk  ru  r4  r5  r6  r   r   r  r  r  rT  rr  r   r   r  r   r   r   r  r  rM  r  r(  r+  r*  r)  rW   r   r   r   rY   rY   K   s   67-r0
 N]

&)
47
GJ
jm
	
  $()-#BBBB !BB '	BB
 BB BB 
BBJ qu2
!2
0:2
JT2
cm2
	2
h*8X~B cg

#&
6@
U_
	
 <$06@, & "&"!%"!%#'!"#'!*.#0> 0> 	0>
  0> 0> 0> 0> 0> !0> 0> 0> !0> 0> 0>  (!0>" #0>$ 
%0>d/
	55 !%"%)!"&%)%*!*."!%:+ :+ 	:+
 :+ :+ :+ :+ :+ #:+ :+  :+ #:+ #:+ :+  (!:+" #:+$ %:+& 
':+x* ""&,0!< <  	<
 *< < < 
<B ""&%),0*.!'&'& 	'&
  '& #'& *'& ('& '& 
'&\ 04*.%/%/ %/
 -%/ (%/ 
%/N. &*$()) 	)
 #) ") 
)* 7;QUdf @, !%*."&'/ '/ 	'/
 '/ '/ '/ '/ '/ ('/  '/ 
'/R. 7; 
@ ?C 

$
LDXL/2/2.1/2?B/2KN/2Y\/2hv/2	/2b4 &#
J
gRG
 >BW[ 	G5 #'+#'!%"&"&"&#'#*.;0;0 	;0
 %;0 !;0 ;0  ;0  ;0  ;0 !;0 ;0 (;0 
;0@ 
 
 	

 %
 !
 
 

"0$ #'+$(00 	0
 0 %0 "0 
0*5 =Ar 
G5 


U%
+
*2-Z
"" " %	"
 !" " 
"2.


6 
   
r   rY   )rQ   r>   )r   r>   rQ   r>   )r!   r>   rQ   r>   )r2   r>   r3   r>   rQ   r>   )
__future__r   r  r  r%   r  r   dataclassesr   r   r   r   typingr   urllib.parser	   r)  r   r_   r   r   r   r"   r*   r5   r8   rY   r   r   r   <module>r     so    "   	   ! - -  ! " )*+	" 
 
 
2j jr   