
    \iC                        % S r SSKJrJrJr  SSKrSSKrSSKrSSKrSSK	r	SSK
r
SSKrSSKrSSKJr   SSKJrJr  Sr0 r\\\\\4   4   \S
'   S(S\\   S\\\4   4S jjr " S S5      r\" 5       r0 r \\\\\4   4   \S'   0 r!\RD                  " 5       r#\RD                  " 5       r$Sq%S r&S r'S r(Sr)\r*Sq+Sq,/ q-S r.S r/S\4S jr0S r1S r2S\3S\S\4S jr4S r5S(S\\   4S  jjr6S(S\\   4S! jjr7S" r8S\3S\4S# jr9S$ r:S)S\\   S%\34S& jjr;S' r<g! \ aH  rSrSSKr\R,                  " \5      r\R3                  S\ 35        \R3                  S	5         SrCGN"SrCff = f)*u  
CTF 题目生成工具模块

本模块提供题目生成过程中的工具函数和状态管理。

核心功能：
---------
1. 生成状态管理 (generation_statuses)
   - 按 task_id 索引，支持多任务并发
   - 步骤状态管理（阶段数量由配置决定）

2. 日志记录 (write_ai_log)
   - 记录 AI 对话到数据库
   - 关联到题目和用户
   - 支持步骤耗时统计

3. 结果持久化
   - 保存生成结果到数据库
   - 支持会话恢复
    )DictAnyOptionalN)StageDetector)save_challenge_recordget_latest_challengeTFu#   数据库操作模块导入失败: u!   将使用文件方式存储数据generation_statusestask_idreturnc                     U (       a   U [         ;   a	  [         U    $ SS0 SSSSSSU S.
$ [         (       a&  [        [         R                  5       S S9n[         U   $ SS0 SSSSSSS	.	$ )
u   获取生成状态

Args:
    task_id: 任务ID，如果为None则返回最新的任务状态（向后兼容）

Returns:
    生成状态字典
Fu   任务状态不存在r   N)
generation_startedmessagestep_statusescurrent_step	completedkey_infoerrorlog_filelog_positionr
   c                 4    [         U    R                  SS5      $ N
created_atr   r	   getks    D   /Users/yu22x/Desktop/ddd_副本138/ctf/app/routes/generator/utils.py<lambda>'get_generation_status.<locals>.<lambda>W   s    GZ[\G]GaGabnpqGr    keyu   等待开始生成...)	r   r   r   r   r   r   r   r   r   )r	   maxkeys)r
   latest_task_ids     r   get_generation_statusr&   7   s     ))&w//
 ',2!# !"   !"  0557=rs">22 $*
 
r    c                   4    \ rS rSrSrS	S jrS rS rS rSr	g)
GenerationStatusProxyh   u9   生成状态代理类，提供向后兼容的字典接口Nc                 8    [        5       nUR                  X5      $ Nr&   r   )selfr"   defaultstatuss       r   r   GenerationStatusProxy.getj   s    &(zz#''r    c                    [         (       a}  [        [         R                  5       S S9nU[         ;   a  U[         U   U'   g S[        [        R                  " 5       5       3nU[         ;  a  [        5       [         U'   U[         U   U'   g g )Nc                 4    [         U    R                  SS5      $ r   r   r   s    r   r   3GenerationStatusProxy.__setitem__.<locals>.<lambda>q   s    K^_`KaKeKefrtuKvr    r!   default-)r	   r#   r$   inttimer&   )r-   r"   valuer%   default_task_ids        r   __setitem__!GenerationStatusProxy.__setitem__n   s~     !4!9!9!;AvwN!44;@#N3C8 %-S-=,>"?"*==;P;R'8<A#O4S9 r    c                     [        5       nX!   $ r+   r&   r-   r"   r/   s      r   __getitem__!GenerationStatusProxy.__getitem__{   s    &({r    c                     [        5       nX;   $ r+   r<   r=   s      r   __contains__"GenerationStatusProxy.__contains__   s    &(}r     r+   )
__name__
__module____qualname____firstlineno____doc__r   r9   r>   rA   __static_attributes__rC   r    r   r(   r(   h   s    C(Br    r(   generation_outputc                      Sq g)u   请求终止生成过程TNgeneration_cancelledrC   r    r   cancel_generationrN      s
      r    c                      Sq g)u   重置终止标志FNrL   rC   r    r   reset_cancel_flagrP      s
     !r    c                      [         $ )u   检查是否请求终止rL   rC   r    r   is_generation_cancelledrR      s
      r    z data/last_generation_result.jsonc                 d    U q SSKnUR                  " [        5      nUR	                  SU  35        g)uL   设置当前题目ID，用于关联日志

Args:
    challenge_id: 题目ID
r   Nu   已设置当前题目ID: )current_challenge_idlogging	getLoggerrD   debug)challenge_idrU   loggers      r   set_current_challenge_idrZ      s1     (x(F
LL,\N;<r    c                 $    U q [        SU  35        g)uG   设置当前用户ID，用于关联日志

Args:
    user_id: 用户ID
u   已设置当前用户ID: N)current_user_idprint)user_ids    r   set_current_user_idr_      s     O	%gY
/0r    resultc                    U R                  S5      (       d0  [        R                  R                  5       R                  S5      U S'   [        (       aX   [
        nU(       a  [        SU S35        O[        S5        [        X5      nU(       a  Uq[        SU 35        g[        S5        g	[        S5        g	! [         a6  n[        S
[        U5       35        [        R                  " 5          SnAg	SnAff = f)u   保存生成结果到数据库，用于会话恢复

Args:
    result: 生成结果字典

Returns:
    bool: 是否成功保存
	timestampz%Y-%m-%d %H:%M:%Su"   使用全局变量中的用户ID: u   ，将关联到生成的题目uA   警告：未找到当前用户ID，题目将不会关联到用户u+   已将生成结果保存到数据库，ID: Tu8   保存到数据库失败：未能获取有效的题目IDFu&   保存生成结果到数据库失败: Nu3   数据库操作不可用，无法保存生成结果)r   datetimenowstrftimeUSE_DATABASE_STORAGEr\   r]   r   rT   	Exceptionstr	traceback	print_exc)r`   r^   rX   db_errors       r   save_generation_resultrl      s     ::k""&//335>>?RS{ 	%G:7)CabcYZ0AL'3$CL>RSPQ 	CD  	:3x=/JK!	s   A
B6 B6 6
C6 ,C11C6c                  (   [         (       a9   [        5       n U (       a&  U R                  S5      q[	        S[         S35        U $  [	        S5        g! [
         a6  n[	        S[        U5       35        [        R                  " 5          SnANGSnAff = f)u   从数据库加载生成结果，用于应用启动时恢复状态

Returns:
    dict: 加载的生成结果，如果没有则返回None
idu+   成功从数据库加载最新题目（ID:    ）u&   从数据库加载生成结果失败: Nu0   数据库操作不可用或找不到题目记录)	rf   r   r   rT   r]   rg   rh   ri   rj   )latest_challengerk   s     r   load_generation_resultrq      s     	"35'7';';D'A$CDXCYY\]^''   

<=  	":3x=/JK!!	"s   6A 
B,BBc                 B   U (       d  gU R                  S5      n/ nSnU Hl  nUR                  5       R                  S5      (       a  U(       + nUR                  U5        MA  U(       a  UR                  U5        M[  UR                  U5        Mn     SR	                  U5      $ )uu   格式化日志内容

Args:
    content: 日志内容
    role: 角色
    
Returns:
    str: 格式化后的内容
u   【空内容】
Fz```)splitstrip
startswithappendjoin)contentrolelinesformatted_linesin_code_blocklines         r   format_content_for_logr     s       MM$EOM::<""5)) --M""4(""4( ""4(  99_%%r    steprz   ry   c                 6   [            [        [        S5      (       dl  [        R                  R	                  5       nUR                  S5      [        l        0 [        l        0 [        l        [        S[        R                   35        / q
U  SU 3n[        [        S5      (       d  0 [        l        U[        R                  ;   aS  [        R                  U   U:X  a  [        SU  SU 35         SSS5        gUS	:w  a  [        S
U  SU 35         SSS5        gU[        R                  U'   [        R                  R	                  5       R                  5       nUS:X  a'  U [        R                  ;  a  U[        R                  U '   SnUS:X  au  U [        R                  ;   aa  [        R                  R                  [        R                  U    5      n[        R                  R                  U5      nX-
  R                  5       n SSS5        g! , (       d  f       g= f)u   记录AI对话日志到数据库

Args:
    step: 当前步骤
    role: 角色 (user/assistant/system)
    content: 消息内容
log_idz%Y%m%d_%H%M%Su   创建新的日志ID: _logged_messagesu!   跳过已记录的消息: 步骤=u	   , 角色=Nsystemu3   发现不同内容的消息在相同位置: 步骤=user	assistant)log_lockhasattrwrite_ai_logrc   rd   re   r   step_start_timer   r]   conversation_log_ids	isoformatfromisoformattotal_seconds)	r   rz   ry   rd   message_keyrb   step_duration
start_timeend_times	            r   r   r   0  s    
|X..##'')C"%,,"?L+-L(+-L(*<+>+>*?@A#%  av& |%677+-L( ,666++K8GC9$yOP/ 
2 !KD6QZ[_Z`ab7 
< 5<$$[1 %%))+557	 6>d,*F*FF1:L((. ;4<+G+G#G!**889U9UVZ9[\J((66yAH%2AACM 	a 
s   C&H
6H
C)H


Hc                      [         $ )u:   获取生成输出

Returns:
    Dict: 生成输出字典
)rJ   rC   r    r   get_generation_outputr   p  s
     r    c                 <    [        U 5      nUR                  SS5      $ )u   检查生成是否已完成

Args:
    task_id: 任务ID，如果为None则使用最新的任务（向后兼容）

Returns:
    bool: 是否已完成
r   Fr,   r
   r/   s     r   is_generation_completedr   y  s     #7+F::k5))r    c                 <    [        U 5      nUR                  SS5      $ )u   获取生成错误信息

Args:
    task_id: 任务ID，如果为None则使用最新的任务（向后兼容）

Returns:
    str: 错误信息
r   Nr,   r   s     r   get_generation_errorr     s     #7+F::gt$$r    c                      / $ )u@   获取完整对话历史

Returns:
    List: 对话历史列表
rC   rC   r    r   get_full_conversation_historyr     s	     Ir    c                 .    [         R                  " U 5      $ )u8   获取 Augment 阶段描述（委托给 StageDetector）)r   get_stage_name)r   s    r   get_step_descriptionr     s    ''--r    c                      [        [        S5      (       a  [        [        S5        [        [        S5      (       a  [        [        S5        [        [        S5      (       a  [        [        S5        Sq[	        S5        g)u8   重置日志ID，用于开始新的生成过程时调用r   r   r   Nu   已重置日志ID和题目ID)r   r   delattrrT   r]   rC   r    r   reset_log_idr     s^     |X&&h'|.///0|.///0  	
()r    total_stagesc                    [            U (       d!  S[        [        R                  " 5       5       3n SSSSUS:X  a  0 O[        U5       Vs0 s H  o"S_M     snUSSSS[        R                  " 5       U S.[        U '   U [
        ;  a	  0 [
        U '   [        S	U  S
US:  a  UOS S35        SSS5        gs  snf ! , (       d  f       g= f)u   初始化生成状态

Args:
    task_id: 任务ID，如果为None则创建一个默认任务
    total_stages: 总阶段数，如果为0则不预设阶段状态（由配置决定）
r4   r   u   正在初始化...TFwaitingN)r   r   r   r   r   r   r   r   r   r   r   r
   u%   已初始化生成状态（任务ID: u   , 阶段数: u   由配置决定ro   )generation_lockr5   r6   ranger	   rJ   r]   )r
   r   is      r   initialize_generationr     s     
 TYY[!1 23G +"&#/1#4RQVWcQd:eQdAi<Qd:e())+(
G$ ++)+g&5gYm\hkl\lL  sD  LE  EH  I  	J+ 
 ;f 
s   AB6	B1AB61B66
Cc           
         U (       d  [        S5        g[        (       d,  SSKnUR                  " [        5      nUR                  S5        g SSKJnJn  Sn[         H3  n UR                  R                  U5      nU(       a  Xl        US-  nM3  M5     UR                  R                  5         [        SU S[!        [        5       SU  35        g! [         a%  n[        S	U S
[        U5       35         SnAM  SnAff = f! [         aY  n[        S[        U5       35        ["        R$                  " 5          WR                  R'                  5         O!    O= f SnAgSnAff = f)u   更新所有本次生成的对话日志，关联到指定题目

Args:
    challenge_id: 题目ID

Returns:
    bool: 是否成功更新
u2   无效的题目ID，无法更新对话日志关联Fr   Nu!   没有需要更新的对话日志T)dbAIConversationLog   u   更新对话日志 u	    失败: u   成功更新 /u     条对话日志关联到题目 u   更新对话日志失败: )r]   r   rU   rV   rD   rW   app.models.database.modelsr   r   queryr   rX   rg   rh   sessioncommitlenri   rj   rollback)	rX   rU   rY   r   r   updated_countr   loges	            r   "update_conversation_logs_challenger     sG    BC""8,89D *FG'--11&9'3$!Q&M  + 	

m_Ac2F.G-HHhiuhvwx  G+F89SVHEFFG  *3q6(34	JJ!	s[   D  -CAD 
C>C93D 9C>>D 
E$,E8EEEEE$r+   )Nr   )=rH   typingr   r   r   os	threadingjsonrc   ri   uuidrer6   #app.services.ai.core.stage_detectorr   app.models.database.operationsr   r   HAS_DB_OPERATIONSImportErrorr   rU   rV   rD   rY   warningr	   rh   __annotations__r&   r(   generation_statusrJ   last_generation_resultLockr   r   rM   rN   rP   rR   GENERATION_RESULT_FILErf   rT   r\   r   rZ   r_   rl   rq   r   r5   r   r   r   r   r   r   r   r   r   rC   r    r   <module>r      s  * ' & 	      	  >8  24 T#tCH~-. 3.8C= .DcN .b 8 *+  02 4T#s(^+, 1   .." >>   
!
  <  )      
=1(4 (V0&@;s ;# ; ;@
*Xc] 
*
%(3- 
%.s .s .
* J8C= Js J>/O  8x(F
NN8<=
NN6778s   
D E&=E!!E&