
    i              	           U d Z ddlZddlZddlZddlmZ ddlmZ ddlmZ ddl	m
Z
 ddlmZ e G d d	             Zi Zeeef   ed
<   de
eef   defdZ	 dde
eef   dededefdZdedee   fdZdededdfdZy)u1  MEMORY.md 관리 모듈 - Frozen Snapshot 패턴.

Hermes Agent의 memory_tool.py MemoryStore 설계를 참고하여
dev2-team 시스템에 맞게 재설계한 경량 메모리 관리 모듈.

주요 기능:
  - Frozen Snapshot: 세션 시작 시 파일을 읽어 FrozenMemory 객체로 캐시.
    재호출 시 동일 객체 반환(캐시). 파일 변경이 세션 중 반영되지 않음.
  - 문자 제한: update_memory()에서 max_chars 초과 시 거부.
  - 인젝션 탐지: update_memory() 호출 시 injection_guard 재사용.
  - 파일 잠금: fcntl.flock 사용 (Linux 전용).

Usage:
    from utils.memory_manager import load_frozen_memory, update_memory

    snapshot = load_frozen_memory("/path/to/MEMORY.md")
    print(snapshot.content)

    ok = update_memory("/path/to/MEMORY.md", "new content")
    N)	dataclass)datetime)Path)Union)scan_contentc                   0    e Zd ZU dZeed<   eed<   eed<   y)FrozenMemoryu9   세션 시작 시 캡처된 메모리 스냅샷 (불변).contentsnapshot_time
char_countN)__name__
__module____qualname____doc__str__annotations__r   int     E/home/jay/workspace/.worktrees/task-2116-dev1/utils/memory_manager.pyr	   r	   !   s    CLOr   r	   _snapshot_cachepathreturnc                 `   t        t        |       j                               }|t        v r	t        |   S t        |      }|j	                         r	 |j                  d      }nd}t        |t        j                         t        |            }|t        |<   |S # t        t        f$ r d}Y Gw xY w)uV  MEMORY.md를 읽어 FrozenMemory 스냅샷을 반환합니다.

    동일 경로를 재호출하면 캐시된 동일 객체를 반환합니다.
    파일이 없으면 빈 FrozenMemory를 반환합니다.

    Args:
        path: MEMORY.md 파일 경로 (str 또는 Path).

    Returns:
        FrozenMemory: 캡처된 스냅샷 객체.
    utf-8encoding )r
   r   r   )r   r   resolver   exists	read_textOSErrorIOErrorr	   r   nowlen)r   resolved	file_pathr
   snapshots        r   load_frozen_memoryr)   1   s     4:%%'(H?"x((XI	))7);G llnw<H
 !)OHO ! 	G	s   B B-,B-new_content	max_charsc                    t        |       j                         }t        |      }|j                  syt	        |      |kD  ry	 |j
                  j                  dd       |j                  |j                  dz         }	 t        |d      }	 t        j                  |t        j                         t        ||       t        j                  |t        j                         |j!                          y# t        $ r Y yw xY w# t        j                  |t        j                         |j!                          w xY w# t        t"        t$        f$ r Y yw xY w)u  MEMORY.md를 새 내용으로 갱신합니다.

    인젝션 패턴 탐지와 문자 수 제한을 검사합니다.
    파일 잠금(fcntl.flock)으로 동시 쓰기를 방지합니다.

    Args:
        path: MEMORY.md 파일 경로 (str 또는 Path).
        new_content: 저장할 새 내용.
        max_chars: 최대 허용 문자 수 (기본값 2200).

    Returns:
        bool: 성공 시 True, 실패 시 False.
    FT)parentsexist_okz.lockw)r   r   r   is_safer%   parentmkdirr"   with_suffixsuffixopenfcntlflockLOCK_EX_atomic_writeLOCK_UNcloser#   RuntimeError)r   r*   r+   r'   scan_result	lock_pathlock_fds          r   update_memoryr@   T   s   $ T
""$I {+K ;)#td;
 %%i&6&6&@AI	y#&	KK/)[1KK/MMO #   KK/MMOWl+ s<   C0 >D8 0C? ;4D8 0	C<;C<?6D55D8 8EEr
   c                     t        |       }|j                  rg S |j                  D cg c]  }|j                   c}S c c}w )uX  메모리 내용에서 인젝션 패턴을 탐지합니다.

    injection_guard.scan_content()를 재사용하여 탐지된
    패턴 이름 목록을 반환합니다.

    Args:
        content: 검사할 문자열.

    Returns:
        list[str]: 탐지된 위협의 pattern_name 목록.
                   안전하면 빈 리스트.
    )r   r0   threatspattern_name)r
   resultthreats      r   scan_memory_injectionrF      s8     '"F~~	.4nn=FF===s   >c                    t        j                  t        | j                        dd      \  }}	 t	        j
                  |dd      5 }|j                  |       |j                          t	        j                  |j                                ddd       t	        j                  |t        |              y# 1 sw Y   )xY w# t        $ r' 	 t	        j                  |        # t        $ r Y  w xY ww xY w)u1   임시 파일 + os.replace()로 원자적 쓰기.z.tmpz.mem_)dirr4   prefixr/   r   r   N)tempfilemkstempr   r1   osfdopenwriteflushfsyncfilenoreplaceBaseExceptionunlinkr"   )r   r
   fdtmp_pathfs        r   r9   r9      s    ##LB
YYr31 	!QGGGGGIHHQXXZ 	! 	

8SY'		! 	!
  	IIh 	  		sH   C AB5'C 5B>:C 	C1C! C1!	C-*C1,C--C1)i  )r   r6   rL   rJ   dataclassesr   r   pathlibr   typingr   utils.injection_guardr   r	   r   dictr   r   r)   r   boolr@   listrF   r9   r   r   r   <module>r_      s   *  	  !    .    ,.c<'( - U39-  ,  L 1
T	
11 1 
	1h>3 >49 >0 s t r   