
    ix!              
          d Z ddlZddlZddlmZmZ ddlmZ ddlmZm	Z	m
Z
 ddlmZ ddlmZ ddlmZ dd	lmZmZmZ dd
lmZ  eddg      Z G d de      Z G d de      Zej7                  d      dd e	e       e	e      fdee   dededefd       Zej7                  d       e	e       e	e      fdedefd       Zej7                  d       e	e       e	e      fdedededefd       Z ej7                  d       e
d       e
d       e	e       e	e      fd ed!ededefd"       Z!ej7                  d#       e	e       e	e      fd$ededefd%       Z"ejG                  d       e	e       e	e      fd&ededefd'       Z$ejK                  d#       e	e       e	e      fd$ed&ededefd(       Z&ejG                  d)       e	e       e	e      fd$ededefd*       Z'y)+u1   프롬프트 관리 API — CRUD + 버전 관리.    N)datetimetimezone)Optional)	APIRouterDependsQuery)	BaseModel)text)Session)get_dbget_current_userrequire_admin)UserAccountz/api/v1/promptsprompts)prefixtagsc                   J    e Zd ZU eed<   eed<   eed<   eed<   dZee   ed<   y)PromptCreatemodulenameversioncontentNschema_json__name__
__module____qualname__str__annotations__r   r        H/Users/manta/Documents/Projects/TheRoad-I1/backend/app/api/v1/prompts.pyr   r      s$    K
ILL!%K#%r!   r   c                   ,    e Zd ZU eed<   dZee   ed<   y)PromptUpdater   Nr   r   r    r!   r"   r$   r$      s    L!%K#%r!   r$   /Fr   active_onlydbcurrent_userc                    d}i }g }| r|j                  d       | |d<   |r|j                  d       |r|ddj                  |      z   z  }|dz  }|j                  t        |      |      j	                         }dd	lm t        |fd
d      }ddlm	}	 g }
 |	|d       D ]+  \  \  }}}|
j                  t        t        |                   - |
D cg c])  }|d   |d   |d   |d   |d   |d   |d   |d   |d   d	+ c}S c c}w )u?   프롬프트 목록 조회. module 필터 + active_only 옵션.zSELECT id, module, name, version, is_active, file_path, created_at, created_by, LENGTH(content) as content_length FROM prompt_templatezmodule = :moduler   zis_active = truez WHERE z AND z ORDER BY module, namer   _version_sort_keyc                 4    | d   | d    | d   xs d      fS )N          r    )rr+   s    r"   <lambda>zlist_prompts.<locals>.<lambda>=   s"    qtQqT#4QqTZR#@Ar!   Fkeyreverse)groupbyc                     | d   | d   fS )Nr-   r.   r    )r1   s    r"   r2   zlist_prompts.<locals>.<lambda>C   s    adAaD\r!   )r4   r-   r.   r/                  )	idr   r   r   	is_active	file_path
created_at
created_bycontent_length)appendjoinexecuter
   fetchallapp.modules.prompt_loaderr+   sorted	itertoolsr6   extendreversedlist)r   r&   r'   r(   queryparams
conditionsrowssorted_rowsr6   finalmodnmgrpr1   r+   s                  @r"   list_promptsrV       s>    UEFJ,-!x,-W\\*555 
%%E::d5k6*335D;AK "E!+3IJ	b3Xd3i() K 	 ! dadAaDQqTqT!AaDdad 	  s   .Dz/modulesc                    | j                  t        d            j                         }ddlm} ddlm}  |t              }|D ]!  }||d      j                  |d   |d   f       # g }t        |j                               D ]m  }||   }	t        |	      }
t        d |	D              }|	D cg c]
  \  }}|s	| }}}|j                  |d	       |r|d   nd
}|j                  ||
||d       o |S c c}}w )u  모듈 목록 + 각 모듈의 프롬프트/버전 수.

    latest_version 은 SQL ``MAX(version)`` 이 lexical (``9.x`` > ``10.x`` 버그)
    이므로 module 별 row 를 모두 fetch 한 뒤 Python ``_version_sort_key`` 로
    numeric-aware 최대값 계산.
    zFSELECT module, version, is_active FROM prompt_template ORDER BY moduler   )defaultdictr*   r-   r.   c              3   ,   K   | ]  \  }}|s	d   yw)r-   Nr    ).0_r>   s      r"   	<genexpr>zlist_modules.<locals>.<genexpr>e   s     FII1s   
Tr3   N)r   totalactive_countlatest_version)rE   r
   rF   collectionsrX   rG   r+   rL   rC   rH   keyslensumsort)r'   r(   rP   rX   r+   	by_moduler1   outr   entriesr]   r^   vr[   versionslatests                   r"   list_modulesrk   L   s    ::dP xz 	 (;!$'I!A$!ad|,  C)*F#GFFF")/'$!QQA'/+T: (!d

ul$
 	 + J 0s   ,
C47C4z/effective/{module}/{name}r   c                 "    ddl m}  || ||      S )u  현재 ``load_prompt`` 가 실제 사용할 source 표시 — DB row + file fallback 모두 검사.

    admin UI 가 prompt_template DB row 만 보고 active prompt 판단하던 문제 해소
    (problems.md #8). winner / fallback_reason / candidate 정보 표시.
    r   )get_effective_source)rG   rm   )r   r   r'   r(   rm   s        r"   get_effective_promptrn   p   s     ?b11r!   z/compare.id1id2c                 6   |j                  t        d      d| i      j                         }|j                  t        d      d|i      j                         }|r|sddlm}  |ddd      |d   |d	   |d
   |d   |d   d|d   |d	   |d
   |d   |d   ddS )u   두 프롬프트 버전 비교.zVSELECT module, name, version, content, schema_json FROM prompt_template WHERE id = :idr=   r   AppErrorprompt.not_foundu(   비교 대상을 찾을 수 없습니다  codemessagestatus_coder-   r.   r/   r8   )r   r   r   r   r   )leftrightrE   r
   fetchoneapp.core.errorsrs   )ro   rp   r'   r(   r1r2rs   s          r"   compare_versionsr      s     
D`c{
HJ  
D`c{
HJ  R,.8bpstt a5"Q%BqEbQRedfghdijqE2a5RUrRSueghiejk r!   z/{prompt_id}	prompt_idc                     |j                  t        d      d| i      j                         }|sddlm}  |ddd      |d   |d	   |d
   |d   |d   |d   |d   |d   |d   |d   d
S )u%   프롬프트 상세 (content 포함).zSELECT id, module, name, version, content, schema_json, is_active, file_path, created_at, created_by FROM prompt_template WHERE id = :idr=   r   rr   rt   '   프롬프트를 찾을 수 없습니다ru   rv   r-   r.   r/   r8   r9   r:   r;   r<   	   )
r=   r   r   r   r   r   r>   r?   r@   rA   r|   )r   r'   r(   rowrs   s        r"   
get_promptr      s     **T	. 	i #(*  ,.8aorss!fAA3q6q6#a&s1vV3q6Q r!   bodyc                    t        j                  t        j                        j	                         }t        t        j                               }|j                  t        d      || j                  | j                  | j                  | j                  | j                  ||j                  d       |j!                          |ddS )u   새 프롬프트 버전 생성.z
        INSERT INTO prompt_template (id, module, name, version, content, schema_json, is_active, created_at, created_by)
        VALUES (:id, :module, :name, :version, :content, :schema_json, false, :created_at, :created_by)
    )r=   r   r   r   r   r   r@   rA   u%   프롬프트가 생성되었습니다)r=   rx   )r   nowr   utc	isoformatr   uuiduuid4rE   r
   r   r   r   r   r   r=   commit)r   r'   r(   r   pids        r"   create_promptr      s     ,,x||
$
.
.
0C
djjl
CJJt  	 T[[$))<<DLL''s"oo	 IIK"IJJr!   c                     |j                  t        d      |j                  |j                  | d      }|j                  dk(  rddlm}  |ddd      |j                          d	d
iS )u5   프롬프트 내용 수정 (같은 버전 내에서).zXUPDATE prompt_template SET content = :content, schema_json = :schema_json WHERE id = :id)r   r   r=   r   rr   rt   r   ru   rv   okT)rE   r
   r   r   rowcountr~   rs   r   )r   r   r'   r(   resultrs   s         r"   update_promptr      sg     ZZb<<0@0@	RTF !,.8aorssIIK$<r!   z/{prompt_id}/activatec                 >   |j                  t        d      d| i      j                         }|sddlm}  |ddd      |d   |d	   }}|j                  t        d
      ||d       |j                  t        d      d| i       |j                          d| d| ddS )ub   이 프롬프트를 활성 버전으로 설정 (같은 module+name의 다른 버전은 비활성).z7SELECT module, name FROM prompt_template WHERE id = :idr=   r   rr   rt   r   ru   rv   r-   zLUPDATE prompt_template SET is_active = false WHERE module = :m AND name = :n)mnz:UPDATE prompt_template SET is_active = true WHERE id = :idTr%   u'    활성 버전이 변경되었습니다)r   rx   )rE   r
   r}   r~   rs   r   )r   r'   r(   r   rs   r   r   s          r"   activate_promptr      s     **TAi"(*  ,.8aorssq63q6DFJJtV$! JJtDi IIKfXQtf4[#\]]r!   )(__doc__jsonr   r   r   typingr   fastapir   r   r   pydanticr	   
sqlalchemyr
   sqlalchemy.ormr   
OrmSessionapp.api.depsr   r   r   app.models.catalogr   routerr   r$   getr   boolrV   rk   rn   r   r   postr   putr   r   r    r!   r"   <module>r      s   7   '  - -   0 @ @ *	+9+	>&9 &&9 &
 C V_ '(8 9	(SM(( 	( 	( (V JV_ '(8 9     F () V_ '(8 9	22
2 	2 	2 *2 JSzSzV_ '(8 9			 	 	 . N V_ '(8 9  ( S V_ ' 6K
KK K K, N V_ ' 6	
 	 	 " $% V_ ' 6^^^ ^ &^r!   