
    6Vib                        S r SSKrSSKrSSKrSSKrSSKJrJrJrJ	r	J
r
  SSKJr  SSKJrJr  SSKJr  SSKJrJr  SS	KJr  \R.                  " \5      r " S
 S5      rS\S\4S jr " S S5      rg)ud   
统一 AI 服务

为题目生成流程提供统一的 AI 调用接口，支持多种 AI 提供商
    N)DictListAnyOptionalCallable)Path   )AIProviderFactoryBaseAIProvider)ToolDefinition)ToolExecutorSandboxConfig)StageDetectorc                      \ rS rSrSr    S>S\S\S\S\S\4
S	 jjrS
 r	S r
S\S\4S jrS\S\4S jrS\S\4S jrS?S\S\S\4S jjrS\4S jrS\\\4   4S jrS\4S jrS\4S jrS rS\S\S\\\4   4S jrS\S\4S jrS\4S  jrS\4S! jrS"\\   S#\S\\   4S$ jrS%\S\\   4S& jr  S@S'\S(\S)\S\\\4   4S* jjrSAS+\S,\\   S-\S.\S/\S\S0\\\4   S\\\4   4S1 jjr S\S\\   4S2 jr!S\S\\   4S3 jr"S%\S\\   4S4 jr#S5\S\4S6 jr$S\\   4S7 jr%S5\S\\   4S8 jr&S9\S\\   4S: jr'S\S\S\4S; jr(S\S.\S+\S,\\   S-\S0\\\4   S\\   4S< jr)S=r*g)B	AIService   u`   统一 AI 服务

封装 AI 提供商和工具执行，为题目生成提供完整的 AI 能力
Nuser_id
output_dirlog_callbackprogress_callbackcategory_idc                     Xl         X l        X0l        X@l        XPl        SU l        U R                  5         SU l        U R                  5         / U l	        SU l
        SSSS.U l        0 U l        / U l        / U l        g)u  初始化 AI 服务

Args:
    user_id: 用户 ID，用于获取用户的 AI 配置
    output_dir: 输出目录（用于沙箱限制）
    log_callback: 日志回调函数
    progress_callback: 进度回调函数
    category_id: 方向 ID（用于设置工作目录）
Nd   '  i )max_messagesmax_tool_results_lengthcompress_threshold)r   r   r   r   r   provider_init_providertool_executor_init_tool_executormessagessystem_promptcontext_configstage_artifactsgenerated_files_filtered_stages)selfr   r   r   r   r   s         K   /Users/yu22x/Desktop/ddd_副本126/ctf/app/services/ai_driver/ai_service.py__init__AIService.__init__   s    " $(!2& 37 6:  " /1 -1  ',"'
 ;= +- 79    c                     [         R                  " U R                  5      U l        U R                  (       ag  U R                  R	                  U R
                  5        U R                  SSU R                  R                   SU R                  R                   S35        g	U R                  SS5        g	! [         a/  nU R                  SS[        U5       35        S	U l         S	nAg	S	nAff = f)
u   初始化 AI 提供商info   已初始化 AI 提供商:  ()warning   未找到可用的 AI 配置error   初始化 AI 提供商失败: N)r
   create_for_userr   r   set_log_callback_on_provider_log_logprovider_namemodel	Exceptionstrr(   es     r)   r   AIService._init_providerR   s    		!-==dllKDM}}..t/D/DE		&$?@[@[?\\^_c_l_l_r_r^sst"uv		)%CD 	!IIg!?AxHI DMM	!s   BB2 B2 2
C+<%C&&C+c                 6   [         R                  " U R                  =(       d    S5      nSnU R                  (       a  [	        [
        5      R                  R                  R                  R                  nUS-  U R                  -  R                  5       n[        U5      nUR                  5       (       d7  US-  R                  5       n[        U5      nU R                  SSU SU 35        OU R                  SSU 35        [        UU R                  US	9U l        g)
u   初始化工具执行器 Nge10r2   u   方向目录不存在: u   ，使用默认目录: r.   u   工作目录设置为: )sandboxr   working_dir)r   create_for_ctf_generationr   r   r   __file__parentresolver=   existsr9   r   _on_tool_logr    )r(   rD   rE   ctf_dircategory_path	ge10_paths         r)   r!   AIService._init_tool_executor_   s      99OO!r

 
 8n++2299@@G %v-0@0@@IIKMm,K ''))$v-668	!)n		)'>}oMdendo%pq		&$;K="IJ ***#
r,   levelmessagec                     U R                   (       a  U R                  X5        [        [        U[        R                  5      nU" SU 35        g)u   记录日志z[AIService] Nr   getattrloggerr.   r(   rP   rQ   log_funcs       r)   r9   AIService._log   s:    e-65&++6<y)*r,   c                 .    U R                  USU 35        g)u   AI 提供商日志回调z[Provider] Nr9   r(   rP   rQ   s      r)   r8   AIService._on_provider_log   s    		%;wi01r,   c                 .    U R                  USU 35        g)u   工具执行日志回调[Tool] NrZ   r[   s      r)   rK   AIService._on_tool_log   s    		%77),-r,   progressstatusc                 L    U R                   (       a  U R                  XU5        gg)u   更新进度N)r   )r(   r`   ra   rQ   s       r)   _update_progressAIService._update_progress   s     !!""8W= "r,   returnc                     U R                   SL$ )u   检查 AI 服务是否可用N)r   r(   s    r)   is_availableAIService.is_available   s    }}D((r,   c                     U R                   (       aW  U R                   R                  U R                   R                  U R                   R                  U R                   R                  S.$ g)u   获取当前 AI 提供商信息)typenamer;   base_urlN)r   provider_typer:   r;   rm   rg   s    r)   get_provider_infoAIService.get_provider_info   sL    ==3333,, MM22	  r,   promptc                 N    Xl         U R                  SS[        U5       S35        g)u?   设置系统提示词

Args:
    prompt: 系统提示词内容
r.   u   已设置系统提示词 (    字符)N)r#   r9   len)r(   rq   s     r)   set_system_promptAIService.set_system_prompt   s&     $		&6s6{m8LMr,   	file_pathc                 .    [        U5      nUR                  5       (       a*  UR                  SS9U l        U R	                  SSU 35        g	U R	                  SSU 35        g	! [
         a(  nU R	                  SS[        U5       35         S	nAg	S	nAff = f)
uK   从文件加载系统提示词

Args:
    file_path: 提示词文件路径
utf-8encodingr.   u#   已从文件加载系统提示词: r2      提示词文件不存在: r4   u   加载提示词文件失败: N)r   rJ   	read_textr#   r9   r<   r=   )r(   rw   pathr?   s       r)   load_system_prompt_from_file&AIService.load_system_prompt_from_file   s    	I	?D{{}}%)^^W^%E"		&$G	{"ST		)'A)%MN 	IIIg!>s1vhGHH	Is   A	A" A" "
B,BBc                 R    / U l         0 U l        / U l        U R                  SS5        g)u   清空对话历史r.   u   已清空对话历史N)r"   r%   r&   r9   rg   s    r)   clear_historyAIService.clear_history   s(    !!		&12r,   stagecontentc                 l    [         R                  " X5      nUSS.nU(       a  UR                  U5        U$ )uE   从 AI 输出中提取阶段关键信息（委托给 StageDetector）rB   )r   raw_summary)r   extract_stage_infoupdate)r(   r   r   r.   artifacts        r)   _extract_stage_artifact!AIService._extract_stage_artifact   s0    //?"26OOD!r,   c           
          U R                  X5      nX0R                  U'   U R                  SSU SUR                  SS5       35        g)uR   保存阶段关键信息

Args:
    stage: 阶段号
    content: AI 输出内容
debugu   保存阶段 u	    摘要: r   rB   N)r   r%   r9   get)r(   r   r   r   s       r)   _save_stage_artifactAIService._save_stage_artifact   sJ     //?&.U#		']5'8<<WY;Z:[\]r,   c                 j    U(       a,  XR                   ;  a  U R                   R                  U5        ggg)u9   跟踪生成的文件

Args:
    file_path: 文件路径
N)r&   append)r(   rw   s     r)   _track_generated_fileAIService._track_generated_file   s-     *>*>>  ''	2 ?9r,   c                 X    [         R                  " U R                  U R                  5      $ )u2   构建上下文摘要（委托给 StageDetector）)r   build_context_summaryr%   r&   rg   s    r)   _build_context_summary AIService._build_context_summary   s!    2243G3GI]I]^^r,   r"   current_stagec           	         [        U5      U R                  S   :  a  U$ U R                  SS[        U5       S35        / nU R                  S   nU R                  S   nU(       a1  US   R                  S5      S	:X  a  UR	                  US   5        US
S nU R                  5       nU(       ap  UR	                  SUS-   S.5        U R                  (       a  U R                  U5      O
[        U5      nU R                  U5      nUR	                  SSU SU S3S.5        [        U5      U:  a  X* S OUn	U	(       a  U	S   R                  S5      S:X  am  [        U5      [        U	5      -
  n
U
S:  aP  [        U
S
-
  SS5       H<  nX   nU/U	-   n	UR                  S5      S:X  d  M$  UR                  S5      (       d  M<    O   U	 H  nUR                  5       nUR                  S5      S:X  a<  [        UR                  SS5      5      U:  a  US   nUSU S[        U5       S3-   US'   UR                  S5      S:X  aA  [        UR                  SS5      5      S:  a"  US   nSU;   a  USS S-   US'   OUSS S-   US'   UR	                  U5        M     U R                  SS[        U5      S
-    S[        U5       S 35        U$ )!u  压缩消息列表，保留关键信息

策略：
1. 保留系统提示词
2. 保留阶段摘要
3. 保留最近 N 条消息
4. 截断过长的工具结果

Args:
    messages: 原始消息列表
    current_stage: 当前阶段
    
Returns:
    压缩后的消息列表
r   r.   u   触发上下文压缩: u    条消息 → 压缩中...r   r   r   rolesystemr	   Nuseru2   

请基于以上历史信息继续当前任务。r   r   	assistantuC   好的，我已了解之前阶段的关键信息。当前在阶段    （u   ），继续执行。tool
tool_callsr   rB   u   
... [已截断，原长度 u    字符]i  |u   
... [已截断]i  u   上下文压缩完成: u    → u
    条消息)rt   r$   r9   r   r   r   r'   _get_stage_id_by_indexr=   _get_stage_namerangecopy)r(   r"   r   
compressedr   max_tool_lencontext_summarystage_id
stage_namerecent_messages	start_idximsgnew_msgr   s                  r)   _compress_messagesAIService._compress_messages   s     x=4../CDDO		&3CM?B]^_
**>:**+DE /8;hqk*|H 557*-cc 
 FJEZEZt22=A`cdq`rH--h7J#`an`oors}r~  T  U  7:(ml6R(=>2X` q155f=GHO(<<I1}y1}b"5A"+C'*eo&=Owwv+5#'',:O:O	 6 #ChhjG wwv&(SB1G-H<-Wi.%,]l%;@]^abi^j]kks>t%t	" wwv+-#cggi6L2MPT2Ti.'>)0$:M)MGI&)0$:M)MGI&g&! #$ 			&3CMA4E3FeCPZOK\\fghr,   	tool_callc                     UR                  S0 5      R                  SS5      nUR                  S0 5      R                  SS5      n[        U[        5      (       a  [        R                  " U5      nUS;   a)  UR                  S5      =(       d    UR                  S5      $ US	;   aA  UR                  S
S5      n[
        R                  " SU5      nU(       a  UR                  S5      $ g!    g= f)uu   从工具调用中提取文件路径

Args:
    tool_call: 工具调用信息
    
Returns:
    文件路径或 None
functionrl   rB   	arguments{})
write_filecreate_filer~   rw   )bashrun_commandcommandz>\s*([^\s]+)r	   N)r   
isinstancer=   jsonloadsresearchgroup)r(   r   	func_nameargscmdmatchs         r)   _extract_file_from_tool_call&AIService._extract_file_from_tool_call6  s    	!j"599&"EI==R044[$GD$$$zz$' 99xx'@488K+@@ 33hhy"-		/37 ;;q>) 	s   BC(  AC( (C,user_message	use_toolsmax_tool_iterationsc                    U R                   (       d  SSSS.$ / nU R                  (       a  UR                  SU R                  S.5        UR                  U R                  5        UR                  SUS.5        U R                  R                  SUS.5        U(       a  [
        R                  " 5       OSnSnSn Xs:  Ga  US	-  nU R                   R                  XES
9nUR                  S5      (       a  U(       a  U[        US   5      -  nSUR                  SS5      US   S.n	UR                  U	5        US    HT  n
U
S   S   nU R                  SSU 35        U R                  R                  U
5      nUR                  SU
S   UUS.5        MV     M  UR                  SS5      nU R                  R                  SUS.5        SUUUR                  S5      S.$ U R                  SSU 35        SWR                  SS5      USS.$ ! [         a:  nU R                  SS[        U5       35        SS[        U5       3US.s SnA$ SnAff = f) uN  发送消息并获取响应

支持工具调用的多轮对话

Args:
    user_message: 用户消息
    use_tools: 是否启用工具调用
    max_tool_iterations: 最大工具调用迭代次数
    
Returns:
    响应字典:
    - content: 最终文本响应
    - tool_calls_count: 工具调用次数
    - success: 是否成功
Fu8   未配置 AI 提供商，请先在 AI 配置页面设置r   )successr   tool_calls_countr   r   r   Nr	   toolsr   r   r   rB   r   r   r   r   rl   r.      执行工具: r   idr   tool_call_idrl   r   Tusage)r   r   r   r   r2   u&   达到最大工具调用迭代次数: u$   达到最大工具调用次数限制)r   r   r   r2   r4      AI 调用失败: )r   r#   r   extendr"   r   get_ctf_toolschatr   rt   r9   r    execute_tool_callr<   r=   )r(   r   r   r   r"   r   r   	iterationresponseassistant_msgr   	tool_nametool_resultfinal_contentr?   s                  r)   r   AIService.chatT  s   * }} U$%   OO --  	& 	#
 	 	#
 	 3<,,.	E	1Q	  ==--h-D <<--)$H\,B(CC$ !,#+<<	2#>&.|&<%M
 OOM2 &.l%;	$-j$9&$A			&N9+*FG '+&8&8&J&J9&U !$*,5dO$-'2	)  &<   %-LLB$?M MM(( +#0*  $(#0,<!)g!6	  IIi#IJ]I^!_`#<<	26$4A	   	IIg!23q6(;< .s1vh7$4 	s%   9D H +H 
I
/I?I
I
languagevulnerabilitiesscene
difficultyextra_requirements	form_datac                 F/  ^d^e^f^g SSK nSSKmdU R                  (       d  SSS.$ [        U R                  S5      (       Ga   U R                  R                  S;   Ga  [        U R                  SU R                  R                  5      n	U R                  S	S
U	 S35        [        U R                  S5      (       a%  U R                  R                  U R                  5        [        U R                  S5      (       a%  U R                  R                  U R                  5        U R                  R                  UU[        U[        5      (       a  UR                  S5      OUUUUS9$ [        [         5      R"                  R"                  R"                  R"                  n
U
S-  nU
S-  nUR%                  SS9  USTdR                  R'                  5       R)                  S5       S3-  me SSKJn  [/        Te5      US'   SUS'   U R                  S	STe 35        S[.        4UdUe4S jjmgU R                  mfS[.        S[.        4UfUg4S  jjnXl
        U R3                  XdXX7=(       d    0 5      n SSKJn  U R4                  (       a  [7        U R4                  5      OSnUS:  aL  UUS!'   S"U;  a  0 US"'   [9        U5       H  nUUS"   ;  d  M  S#US"   U'   M     U R                  S	S$U S%35        OU R                  SS&5         U(       a1  U R;                  U5        U R                  S	S([7        U5       S)35        OxUS*;   a  US+-  S,-  S--  nOUS+-  S,-  S.-  nUR=                  5       (       a0  U R?                  [/        U5      5        U R                  S	S/U 35        OU R                  SS0U S135        / nU(       Ga   SS2K J!n  URD                  R                  U5      nU(       Ga~  URG                  5       nU GHg  nUR                  S35      nUR                  S4U5      nUR                  S55      nUR                  S6S5      nU(       a  US7;   a  MY  UR                  U5      nUb  US8:X  a  Mu  SnUS9;   a  [        U[H        5      (       a]  S:RK                  U Vs/ s H>  nU(       d  M  [/        [        U[        5      (       a  UR                  SU5      OU5      PM@     sn5      nGO([        U[.        5      (       a  UnGO[/        U5      nGOUS;:X  a  [        U[        5      (       a  UR                  S[/        U5      5      nGOUR                  S</ 5      n U  H~  n![        U![        5      (       a  U!R                  S=5      OU!n"U"U:X  d  M3  [        U![        5      (       a+  U!R                  S4U!R                  S=[/        U!5      5      5      O
[/        U!5      n  O   U(       d  [/        U5      nGO US>:X  Ga  [        U[        5      (       a  UR                  S?5      (       a  GM,  UR                  S[/        U5      5      n#U#(       a  U#RM                  5       S@;   a  GMe  U#(       a  U#RM                  5       (       d  GM  UR                  SA5      n$U$(       aA  [        U$[        5      (       a$  U$R                  SS85      n%U%(       a  U# SBU% 3nOEU#nOBU# SBU$ 3nO:U#nO7[/        U5      RM                  5       S@;   a  GM   [/        U5      nO[/        U5      nU(       d  GM!  URM                  5       (       d  GM9  URM                  5       S@;   a  GMP  URO                  SCU SDU 35        GMj     U(       d6  [        U[H        5      (       a  S:RK                  U5      OUn&SFU 3SGU& 3SHU 3/nU(       a7  URM                  5       (       a"  URO                  SIURM                  5        35        SJRK                  U5      SJ-   n'[        U[H        5      (       a  S:RK                  U5      OUn&U R                  S	SKU SLU SLU& 35        U R                  S	SMU' 35        Sn(U R4                  (       aO  U R4                  S   n)U)R                  SSN5      n*U RQ                  U(SOSPU* SQ35        U RQ                  U(SRU* SS35        O&U RQ                  SSOST5        U RQ                  SSRSU5        U(n+Sn,Sn-SVn.Sn/SWn0/ n10 U l)        / U l*        / n2U RV                  (       a  U2RO                  SXU RV                  SY.5        U2RO                  SZU'SY.5        [X        RZ                  " 5       n3S[n4 Sn5U5U.:  Gav  U5S\-  n5[7        U25      U R\                  S]   :  aC  U+U4:  a=  Tg" S^[7        U25       S_35        U R_                  U2U+5      n2U+n4Tg" S`[7        U25       35        U2(       a  U2S[   n6U6Sa   SZ:X  aY  Tg" SJSb 35        Tg" ScU5 Sd35        Tg" Sb 5        U6Se   n7[7        U75      Sf:  a  Tg" U7SSf Sg[7        U75       S)3-   5        OiTg" U75        O`U6Sa   Sh:X  aW  Tg" SiU5 SjU6R                  SSk5       Sl35        U6Se   n8[7        U85      Sm:  a  Tg" U8SSm Sg[7        U85       S)3-   5        OTg" U85        U R                  Ra                  U2U3Sn9n9U9R                  SeS85      n:U:(       aS  Tg" SJSb 35        Tg" ScU5 So35        Tg" Sb 5        [7        U:5      Sp:  a  Tg" U:SSp Sg[7        U:5       S)3-   5        OTg" U:5        U Rc                  U:5      n;Sn<U;b  U R4                  (       a{  U;S\-
  n=SU=s=::  a  [7        U R4                  5      :  a  O  OU=n<O]U;S:  aI  U R                  SSqU; Sr[7        U R4                  5       Ss[7        U R4                  5      S\-
   StU+ 35        Sn<OU;S:  a  U;S\-
  OSn<U<cy  U R4                  (       ah  [e        U R4                  5       HO  u  n>n?[/        U?R                  S3S85      5      n@U?R                  SS85      nASuU@ 3U:;   d  SvW@ 3U:;   d  WAU:;   d  MM  U>n<  O   U<GbH  U<U+:w  GaA  U<U+:  a}  U R4                  (       a  U Rg                  U+5      O
[/        U+5      nBU R4                  (       a  U Rg                  U<5      O
[/        U<5      nCU R                  SSwU+ SxWB SyU< SxUC Sz3	5        Sn<GO#U<U+:  a  U:(       a  U Ri                  U+U:5        [9        U+U<5       H  nDU RQ                  UDSRSvUD S{35        M     U<n+Sn/U R4                  (       a  U Rg                  U+5      O
[/        U+5      n@U Rk                  U@5      nAU RQ                  U+SOS|UA 35        U R                  S	S}U+ SxU@ S~UA 35        GOeU/S\-  n/U R4                  (       a  [7        U R4                  5      S\-
  OSnEU/U0:  Ga.  U+WE:  Ga'  U+S\-   nFU RQ                  U+SRSvU+ S35        UFn+Sn/U R4                  (       a  U Rg                  U+5      O
[/        U+5      n@U Rk                  U@5      nAU RQ                  U+SOS|UA 35        U R                  SSU+ SxU@ S~UA 35        U R4                  (       a  U+[7        U R4                  5      :  an  U R4                  U+   nG[/        UGR                  S3U+5      5      n@UGR                  SSvU@ 35      nASU@ SDUA S3nHU2RO                  SZUHSY.5        Tg" SU+ SU@ SUA S35        U,c/  U Rm                  U:5      nIUI(       a  WIn,U R                  S	SU, 35        U9R                  S5      (       Ga^  U-[7        U9S   5      -  n-Tg" SiU5 S[7        U9S   5       S35        SU:U9S   S.nJU2RO                  UJ5        U9S    GH  nKUKS   S   nLUKR                  S0 5      R                  SS5      nMTg" SUL 35        [7        UM5      S:  a  Tg" SWMSS  S35        OTg" SWM 35        U R                  S	SWL 35         SSK7nN[        WM[.        5      (       a  WNRp                  " WM5      OWMnOWLS;   a  SWO;   a  WL SWOS    3nPOWLnP U1RO                  WP5        [7        U15      S:  a  U1Rs                  S5        U,c  U Ru                  WK5      n,U Rw                  WK5      nQUQ(       a  U Ry                  WQ5        U Rz                  R}                  WK5      nR[7        UR5      S:  a  Tg" SWRSS  S[7        UR5       S)35        OTg" SWR 35        U2RO                  ShWKS3   WLWRS.5        GM     U R4                  (       Gaa  U+[7        U R4                  5      S\-
  :  nSUS(       Ga>  U,(       Ga6  SS/nT[7        U15      S:  Ga"  U1SS nUSUUS   ;   a  WUS   R                  S5      S   OWUS   nVWUS   UUS\   s=:X  a  WUS   s=:X  a	  WUS   :X  a  O  OWVWT;   a  SWUS   ;   a  WUS   R                  SS\5      S\   OS8nWUW(       a  SWW S3OS8nXU R                  SSWV SUX S35        Tg" SUV SUX S35        U RQ                  U+SRS5        U R4                  (       a8  [9        [7        U R4                  5      5       H  n>U RQ                  U>SRS85        M     U R                  S	S5        SU:U-U,S.$ G	MB  U R                  5       nYSnSU R4                  (       a  U+[7        U R4                  5      S\-
  :  nSWS(       a  U,(       a  U R4                  (       a  [7        U R4                  5      S\-
  OU+nZU RQ                  UZSRS5        U R                  S	S5        U R4                  (       a8  [9        [7        U R4                  5      5       H  n>U RQ                  U>SRS85        M     SU:U-U,S.$ U2RO                  SU:SY.5        Sn[U R4                  (       ag  SSKJn  UR                  S"0 5      n\Sn][7        U R4                  5      n^[9        U^5       H!  n>W\R                  U>5      n_U_SR:X  d  M  W]S\-  n]M#     W]W^:  a  Sn[W[(       a\  U,(       aU  U R                  S	S5        U RQ                  U R4                  (       a  [7        U R4                  5      S\-
  OU+SRS5        SU:U-U,S.$ WS(       Gd;  U R4                  (       Ga)  W[(       Gd!  SSKJn  UR                  S"0 5      n\U\R                  U+5      n`U`SR:w  a_  U R4                  S[   na[/        UaR                  S3S85      5      nYUaR                  SS5      nbSU+ SUY SUb S3ncU2RO                  SZUcSY.5        GM  U+[7        U R4                  5      S\-
  :  aw  U+S\-  n+U R4                  (       a  U Rg                  U+5      O
[/        U+5      n@U Rk                  U@5      nAU RQ                  U+SOS|UA 35        U R                  S	SU+ SxU@ S~UA 35        GMb  U,c  U2RO                  SZSSY.5        GM|   U R                  SSU. 35        U,(       a  U R4                  (       a9  [9        [7        U R4                  5      5       H  n>U RQ                  U>SRS85        M     O]U R4                  (       a9  [9        [7        U R4                  5      5       H  n>U RQ                  U>SRS85        M     OU RQ                  U+SRS85        SSU-U,SS.$ SSU. S3U-S.$ ! [0         a   nU R                  SSU 35         SnAGNSnAff = f! [0         a   nU R                  SS'U 35         SnAGNSnAff = fs  snf ! [0         aT  nU R                  SSEU 35        SFU 3SG[        U[H        5      (       a  S:RK                  U5      OU 3SHU 3/n SnAGNSnAff = f!   WLnP GN*= f! [0         a:  nU R                  SS[/        U5       35        SS[/        U5       3U-S.s SnA$ SnAff = f)u  生成 CTF 题目（模拟 Augment 八轮流程）

使用预设的提示词和工具，生成完整的 CTF 题目
实现分阶段执行和验证，确保题目质量
Args:
    language: 编程语言
    vulnerabilities: 漏洞类型列表
    scene: 场景
    difficulty: 难度（中文：入门/简单/中等/困难）
    extra_requirements: 用户额外要求
    category_id: 方向ID（如 'web'）
    form_data: 表单数据（可选）
    
Returns:
    生成结果
r   Nr4      未配置 AI 提供商)ra   rQ   rn   )	anyrouteragentrouteraugmentr:   r.   u
   检测到 u$    提供商，使用 CLI 模式生成set_progress_callbackr7   rl   )r   r   r   r   r   r   rC   logsT)exist_okai_service_z%Y%m%d_%H%M%Sz.txt)generation_statuslog_filelog_positionu   日志文件: r2   u   设置日志文件失败: rQ   c                   >  [        TSSS9 nTR                  R                  5       R                  S5      nUR	                  SU SU  S35        UR                  5         SSS5        g! , (       d  f       g= f!    g= f)	u   写入日志到文件ary   rz   z%H:%M:%S[] 
N)opendatetimenowstrftimewriteflush)rQ   f	timestampr   r   s      r)   write_to_log6AIService.generate_ctf_challenge.<locals>.write_to_log  sn    (C':a ( 1 1 5 5 7 @ @ LIGGa	{"WIR89GGI ;::s)   A: AA) A: )
A73A: 7A: :A>rP   c                 ^   > T" SU R                  5        SU 35        T(       a	  T" X5        g g )Nr   r   )upper)rP   rQ   original_log_callbackr  s     r)   enhanced_log_callback?AIService.generate_ctf_challenge.<locals>.enhanced_log_callback$  s.    1U[[]O2gY78$%e5 %r,   total_stagesstep_statuseswaitingu
   初始化 
    个阶段u<   未找到阶段配置，阶段状态将由配置动态决定u   初始化阶段状态失败: u$   已从数据库加载系统 Prompt (rs   )   入门   简单z.augmentruleszctf-generation-guide-easy.mdz#ctf-generation-guide-medium-hard.mdu!   已从文件加载系统 Prompt: r|   u   ，且数据库中没有配置CategoryConfigr   labelrk   visible)r   rB   )multi_selectmulti_select_categorized, selectoptionsvalueselect_with_subno_scene)u	   无场景u   无特定场景noneNonerB   	sub_scene - z- u   ：u)   根据表单配置构建指令时出错: u   - 难度：u   - 漏洞类型：u   - 编程语言：u   - 额外要求：r   u   开始生成 CTF 题目: z / u   用户指令内容:
u   用户输入需求
processingu   正在处理: z...	completedu	   已确认u   正在处理用户需求...u   用户需求已确认r      r   r   r   r   r	   r   u   
[上下文管理] 消息数 u    达到阈值，触发压缩...u&   [上下文管理] 压缩后消息数: r   z<============================================================u   [轮次 u   ] 发送给 AI 的消息:r   i  u   
... (截断，共 r   u	   
[轮次 u   ] 工具执行结果 (unknownz):i  r   u   ] AI 响应:r   u   检测到阶段编号 u    超出配置范围（共u   个阶段，索引0-u7   ），忽略此次阶段切换，保持在当前阶段 u   阶段   阶段 u"   检测到阶段回退：从阶段  (ID: u   ) 回退到阶段 u.   )，忽略此变更以保护已完成的工作u    完成u   正在执行: u   进入阶段 ):    u    完成（超时推进）u%   阶段超时，强制推进到阶段 u   请开始阶段u   。u    
[系统] 强制推进到阶段 r   z: u   ），发送引导消息u   检测到输出目录: r   u   ] AI 请求执行 u    个工具:r   r   r   r   r   u   
  📌 工具:   u
     参数: u   ... (截断)r   )list_directory	read_filer~   :   u
     结果: u   ... (截断，共 r   r,  r-           u
    (路径: r1   u"   检测到重复执行只读工具 u    4次u   ，在最后阶段强制停止u,   
[系统] 检测到重复执行只读工具 u   ，强制停止循环执行
u$   检测到循环执行，强制完成u   题目生成完成!r   )ra   r   r   r   Fu   题目生成完成u-   检测到所有阶段已完成，返回结果u   成品输出u"   请继续执行，当前在阶段 u   ，需要完成到阶段 u   ）。u   自动推进到阶段 uf   请创建输出目录并生成题目文件。输出目录格式：output/YYYYMMDD_HHMMSS_题目名称/u   达到最大迭代次数: u-   达到最大迭代次数，但生成已完成u   达到最大迭代次数)ra   r   r   r   r2   u   达到最大迭代次数 (u   )，生成未完成)ra   rQ   r   u   生成失败: )A
subprocessr   r   hasattrrn   rT   r9   r   r   r7   r   generate_ctf_challenger   dictr   r   rG   rH   mkdirr   r   app.routes.generator.utilsr   r=   r<   _load_prompt_from_databaser'   rt   r   ru   rJ   r   app.models.database.modelsr  queryget_form_fieldslistjoinstripr   _update_stage_progressr%   r&   r#   r   r   r$   r   r   _detect_stage	enumerater   r   r   _detect_output_dirr   r   pop_detect_output_dir_from_toolr   r   r    r   split_get_last_stage_id)hr(   r   r   r   r   r   r   r   r4  r:   project_rootge10_dirlog_dirr   r?   r
  r#   r  r   prompt_fileinstruction_linesr  categoryform_fieldsfieldfield_idfield_label
field_typefield_visiblefield_valueformatted_valuevr  opt	opt_value
scene_namer!  sub_scene_namevuln_struser_instructionfirst_stage_indexfirst_stagefirst_stage_namer   r   total_tool_callsmax_iterationsstage_iteration_countmax_stage_iterationsrecent_tool_callsr"   r   last_compress_stager   last_msgmsg_contenttool_contentr   r   new_stage_num	new_stagestage_indexidxr   r   r   current_stage_idnew_stage_idsmax_stage_index
next_stagestage_config
prompt_msgdetected_dirr   r   r   	tool_argsr   parsed_argstool_call_keygenerated_filer   is_last_stageread_only_tools	last_four
first_tool	path_infopath_msglast_stage_idlast_stage_indexall_stages_completedr  completed_counttotal_countra   current_statuslast_stage_configlast_stage_namecontinue_msgr   r   r	  r  sh                                                                                                       @@@@r)   r6   AIService.generate_ctf_challenge  s   " 	}}!3  4==/22t}}7R7RV}7}#DMM?DMMD_D_`MIIf
=/9]^_t}}&=>>33D4J4JKt}}&899..t/@/@A==77! /+5eT+B+Beii'%#5' 8   H~,,33::AA&('t${8+<+<+@+@+B+K+KO+\*]]abb	CD,/Mj)01n-IIfxj9:
	# 	 	 !% 1 1	6 	6s 	6 	6
 2 77QYlq  tC  AC  D	FD9=9N9N3t445TULa4@!.1 #*;;9;%o6 |,A 1/ BB@I)/:1= - 		&J|nJ"GH		)%cd ""=1IIf DSEWDXX`ab 11&3g=@^^&3g=@ee!!##11#k2BC		&$Ek]"ST		)'A+Nl%mn bE)//33K@"*":":"<K "-#(99T?&+ii&B%*YYv%6
(-		)T(B  -<R0R$ '0mmH&=&.+2C$ +/%)UU)+t<<26))  {F  =L  {Fuv  JK=pSU_`acgUhUhvqAQno=p  {F  =L  3M!+K!=!=2=25k2B'83)+t<<2=//&#kJZ2[ +0))Ir*B+2CDNsTXDYDY0@_bI'0K'?jtuxz~jj#'''377SZ\_`c\dKe:f  FI  JM  FN(-	 ,3
 (769+6FO'+<<)+t<<#.??:#>#>$,-8__VSEU-V
'1Z5E5E5GK5$,'19I9I9K9K$,,7OOK,H	#,'1)T'B'B9Bvr9R+9AKCP^O_>`O>HO=GLI;:W6@O $'{#3#9#9#;?s#s$,25k2B /2+.>O +?/D/D/F/F.446:nn (-44r+c/IZ5[\e "-| !5?QU5V5Vtyy1\kHj\*#H:.#H:.! "4":":"<"<$$'89K9Q9Q9S8T%UV99%67$> 2<OT1R1R499_-Xg		&5j\XJcRZQ[\]		&12B1CDE   //2K*v7KL''(9<>ZjYkknIop''(9;K[J\\eHfg ''<9VW'';8OP *
 !"!   "! OOX$:L:LMN4DEF ,,. !E	In,Q	 MT%8%89M%NN!$77 #A#h-Po!pq#66xOH*7' #I#h-!YZ '|H'61$r&]3$x	{:S%TU$x1&.y&9{+d2(Ud);@TUXYdUeTffn>o)op(5!&)V3$z)<RS[S_S_`fhqSrRssu%vw'/	':|,t3(et)<AUVYZfVgUhhp?q)qr(6  ==--he-D",,y"5  2fX/ 8I;l!CD F8-7|e+$WVe_9McRYl^[c7d%de$W- !% 2 27 ; !	 ,,,&3a&7Hc$2G2G.HH(3I*Q. !IIi3I-Xqruvz  wL  wL  sM  rN  Nb  cf  gk  g|  g|  c}  ~  c  b@  @w  xE  wF  2G  H(,I :G9JMA$5PQ	 $)>)>&/0E0E&F
U#&uyyr':#;%*YYvr%:
$XJ/7:z>RV]>]&'1(+I! 'G (Y--G =0Y]YnYn4+F+F}+Utw  yF  uG(QUQfQft'B'B9'Mlopylz		)/QR_Q``fgwfx  yK  LU  KV  V\  ]i  \j  jX  .Y  Z %)	"]2 # 55mWM!&}i!@A 77;'RSQTT[H\] "A )201-QUQfQf4#>#>}#Mlop}l~%)%9%9(%C
33M<SablamQno		&M-xjX[\f[g*hi *Q.) IMH]H]c$*?*?&@1&DcdO -0DDYhIh%2Q%6
33M;RYZgYh  iB  QC  D(201-QUQfQf4#>#>}#Mlop}l~%)%9%9(%C
33M<SablamQno		)/TUbTccijrissv  xB  wC  .D  E  00]SI^I^E_5_+/+@+@+OL'*<+;+;D-+P'QH)5)9)9&GH:BV)WJ+:8*C
|SV)WJ$OOV
,ST(+L]O[^_g^hhjkujv  wO  *P  Q %#'#:#:7#CL#%1
		&,CJ<*PQ <<--$H\,B(CC$ !:i[8J3xXdOeKfJggr!st !,#*&.|&<%M
 OOM2 &.l%;	$-j$9&$A	$-MM*b$A$E$EkSW$X	 %'8%DEy>C/(:io5Fl)ST(:i[)AB		&N9+*FG6'CMiY\C]C]$**Y*?clK(,KKPVZePe3<+Q{6?R>S0T 1:
 *00?01A5-11!4 &-)-)J)J9)UJ *.)J)J9)U) 66~F '+&8&8&J&J9&U {+c1(:k$36G5HHZ[^_j[kZllt)uv(:k])CD !$*,5dO$-'2	) g &<z ,,,)6#d>S>S:TWX:X)X(Z/?.MO
  ##45:,=bc,B	KNR[\]R^K^Yq\-?-?-DQ-Gdmnodp
 %.aLIaL$`IaL$`T]^_T`$`$./$AQTXabcXdQd	!0B0B30J10MjlILUI;a/H[]H$(IIi;]^h]iinownx  yW  :X  %Y$03`ak`llqrzq{  |Y  2Z  %[$($?$?{  ]C  %D'+'<'<38T=R=R9S3TC,0,G,G[Z\,] 4U$(IIf6K$L2;4;<L6@	,& %&  %)$;$;$=M$)M,,)6#d>S>S:TWX:X)X$MQMbMb3t/D/D+E+Ihu(334DkSgh		&*?@  00',S1F1F-G'H $ ; ;Cb Q (I '0(/0@*4	   !(QR 05,00T,=,A,A/SU,VM./O*-d.C.C*DK',['9)6):):3)?#)[#8$3q$8O (:
  /+=7; 4 0J IIf.]^ 77Z^ZoZoD<Q<Q8RUV8V  vC  EP  Rf  g*3,34D.8	$   -1F1F1FOcT,=,A,A/SU,VM-:->->}-MN  .<484I4I"4M 1034E4I4I$PR4S0T2C2G2GP^2_1STaSbb{  }J  |K  KN  O^  N_  _e  0f (L0Y Z ( $13t7L7L3MPQ3Q#Q$1Q$6M]a]r]rt/J/J=/Yx{  }J  yKH151E1Eh1OJ$($?$?|_mnxmy]z${$(IIf8N}o]cdlcmmpq{p|6}$~$, &-$OO(. ,T-  % IIi#=n=M!NO (($S)>)>%?@33CbI  A ,,#(T-B-B)C#DC 77["M $E 33M;PRS' O(8",9  "77GGZ[$4 A  	CIIi#=aS!ABB	C^  	FIIi#@!DEE	Ff =L~  		)'PQRPS%TU!*.'jQ`bfFgFg		/(Bm|'}~'z2%!@6,5MF  	IIgAx89!+CF84$4 	s/   .AZ !AAZ? >"AZ? !AZ? /CA[1 A[,
6A[,
B*A[1 >FA[1 A[1 #3A[1 >K"A] $OA] (AA]@+A] @,A]@.IA] I?C.A] M.A9A] O+A3A] QH(A] Z	A] Z
AZ<ZAZ7Z7AZ<Z?
A[)[	A[$[$A[)[,A[1 [1
A][;A	A]
]
A]]A]]A] ]
A^ ]&/A^^A^ ^A^ c                 .    [         R                  " U5      $ )u?   从 AI 输出中检测当前阶段（委托给 StageDetector）)r   detect_stage)r(   r   s     r)   rB  AIService._detect_stage  s    ))'22r,   c                     [        [        5      R                  R                  R                  R                  n[        US-  5      n[        R
                  " X5      $ )u;   从内容中检测输出目录（委托给 StageDetector）rC   )r   rG   rH   r=   r   detect_output_dir)r(   r   rI  rJ  s       r)   rD  AIService._detect_output_dir  sC    H~,,33::AA|f,-..wAAr,   c                    SSK nSSKn UR                  S0 5      R                  SS5      n[        U[        5      (       a  UR
                  " U5      nS H  nXT;   d  M
  XE   nUR                  " S[	        U5      5      nU(       d  M3  UR                  S5      n[        [        5      R                  R                  R                  R                  n	U	S	-  S
-  U-  n
[	        U
5      s  $    g!    g= f)u{   从工具调用中检测输出目录

Args:
    tool_call: 工具调用信息
    
Returns:
    输出目录路径或 None
r   Nr   r   r   )r~   rw   	directoryr   zoutput/(\d{8}_\d{6}_[^/\s"\']+)r	   rC   output)r   r   r   r   r=   r   r   r   r   rG   rH   )r(   r   r   r   r   keyr  r   dir_namerI  	full_paths              r)   rF  &AIService._detect_output_dir_from_tool  s     		==R044[$GD$$$zz$' E; IEII&H#e*UEu#(;;q>'+H~'<'<'C'C'J'J'Q'Q$06$9H$Dx$O	"9~- E 	s   AC+ %C+ AC+ (C+ +C/r   c                 z   U R                   (       aR  U R                    HB  n[        UR                  SS5      5      [        U5      :X  d  M-  UR                  SSU 35      s  $     UR                  SS5      R	                  5       (       a  [        U5      OSnUb  [        R                  " U5      $  SU 3$ !    N	= f)uP   获取阶段名称（优先从配置中获取，否则委托给 StageDetector）r   rB   rl   r'  .N)r'   r=   r   replaceisdigitintr   get_stage_name)r(   r   r   
numeric_ids       r)   r   AIService._get_stage_name  s       ..uyyr*+s8}< 99Vwxj-ABB /
	*2*:*:3*C*K*K*M*MXSWJ%$33J?? &
 
##	s   %A
B6 6B:c                 z    U R                   (       a*  U R                   S   n[        UR                  SS5      5      $ g)u'   获取配置中的最后一个阶段 IDr   r   rB   N)r'   r=   r   )r(   
last_stages     r)   rH  AIService._get_last_stage_id  s4      ..r2Jz~~dB/00r,   c                     U R                   (       d  g[        U R                   5       H1  u  p#[        UR                  SS5      5      [        U5      :X  d  M/  Us  $    g)u"   根据阶段 ID 获取阶段索引Nr   rB   )r'   rC  r=   r   )r(   r   rm  r   s       r)   _get_stage_index_by_id AIService._get_stage_index_by_id  sK    $$#D$9$9:JC599T2&'3x=8
 ; r,   indexc                     U R                   (       aK  SUs=::  a  [        U R                   5      :  a+  O  g[        U R                   U   R                  SS5      5      $ g)u!   根据阶段索引获取阶段 IDr   r   rB   N)r'   rt   r=   r   )r(   r  s     r)   r    AIService._get_stage_id_by_index  sM      Q%%L#d6K6K2L%L t,,U377bABBr,   c                    U R                   (       a  U R                  XU5        U R                  (       a  U R                  U5      O
[        U5      nU R	                  U5      nU R                  SSU SU SU SU SU 3
5        g)u   更新阶段进度（兼容前端显示）

Args:
    stage: 阶段索引 (0-based)
    status: 状态 (waiting, processing, completed, error)
    message: 消息
r   r'  r(  r  r)  r"  N)r   r'   r   r=   r   r9   )r(   r   ra   rQ   r   r   s         r)   rA   AIService._update_stage_progress  s~     !!""5':9=9N9N4..u5TWX]T^))(3
		'WUG6(2j\VHTWX_W`abr,   c                     SSK Jn  SSKJn  SSKJn	Jn
  U	" 5       (       d  U R                  SS5        gUR                  R                  U5      nU(       d  U R                  SSU 35        gS	S
SSS.nUR                  US	5      nSn UR                  SS9nSU;   a,  [        US   [        5      (       a  US   R                  S5      nUR                  U5      n[        U[        5      (       a  [        U5      OSn/ nU(       Ga0  U GH'  n0 UEnUR                  S5      nU(       Ga   SU;   Ga  SU;   a]  [!        UR#                  S5      S   R%                  5       5      nUU:  d*  U R                  SSUR                  S5       SU S35        M  GOSU;   a]  [!        UR#                  S5      S   R%                  5       5      nUU:  d*  U R                  SSUR                  S5       SU S35        M  GO(SU;   a]  [!        UR#                  S5      S   R%                  5       5      nUU:  d+  U R                  SSUR                  S5       SU S35        GMQ  OSU;   a]  [!        UR#                  S5      S   R%                  5       5      nUU::  d+  U R                  SSUR                  S5       SU S35        GM  ObSU;   a\  [!        UR#                  S5      S   R%                  5       5      nUU:X  d+  U R                  SSUR                  S5       SU S35        GM  UR                  S#5      (       a/  US#   nUR                  S$5      (       a  US$   S%-   U-   US$'   OUUS$'   UR                  SS&5      R%                  5       =(       d     UR                  S$S&5      R%                  5       nU(       dl  UR                  S!S"5      =(       d    UR                  S'S"5      nU(       d:  U R                  SSUR                  S5       S(UR                  S)5       S*35        GM  UR+                  U5        GM*     GO	UR-                  5       nU(       d  U R                  SS+U S,35        gU GH  n0 UEnUR                  S5      nU(       Ga   SU;   Ga  SU;   a]  [!        UR#                  S5      S   R%                  5       5      nUU:  d*  U R                  SSUR                  S5       SU S35        M  GOSU;   a]  [!        UR#                  S5      S   R%                  5       5      nUU:  d*  U R                  SSUR                  S5       SU S35        M  GO(SU;   a]  [!        UR#                  S5      S   R%                  5       5      nUU:  d+  U R                  SSUR                  S5       SU S35        GMQ  OSU;   a]  [!        UR#                  S5      S   R%                  5       5      nUU::  d+  U R                  SSUR                  S5       SU S35        GM  ObSU;   a\  [!        UR#                  S5      S   R%                  5       5      nUU:X  d+  U R                  SSUR                  S5       SU S35        GM  UR                  S-5      (       a  UUS-   ;   a  US-   U   nUR                  S)5      (       a  US)   US)'   UR                  S.5      b  US.   US.'   UR                  S/5      (       a  US/   US/'   UR                  S5      (       a  US   US'   UR                  S$5      (       a  US$   US$'   UR                  S00 5      n[        U[        5      (       aj  UU;   ad  UU   nU(       aX  [        U[        5      (       aC  UR                  S1S&5      nU(       a*  UR                  S$5      (       a  US$   S%-   U-   US$'   OUUS$'   SnUR                  S-5      (       a"  UUS-   ;   a  US-   U   nUR                  S25      nU(       d  UR                  S25      nU(       aO  UR%                  5       (       a:  UR%                  5       n UR                  S$5      (       a  US$   S%-   U -   US$'   OU US$'   UR                  SS&5      R%                  5       =(       d     UR                  S$S&5      R%                  5       nU(       dl  UR                  S!S"5      =(       d    UR                  S'S"5      nU(       d:  U R                  SSUR                  S5       S(UR                  S)5       S*35        GM  UR+                  U5        GM     UR.                  UU[        U[        5      (       a  S3R1                  U5      OU[        U[        5      (       a  UR                  S)5      OUUR                  S4S55      UR                  S6S75      S8.n!UR3                  5       n"U"(       Ga"  UU";   Ga  U"U   R                  S90 5      n#U#R                  S:S;5      U!S:'   U#R                  S<S;5      U!S='   U#R                  S>S?S@/5      U!S>'   U#R                  SASB5      U!SA'   / n$U"R5                  5        H  u  n%n&U&R                  S90 5      n'U'R                  S<S5      n(U'R                  S:S5      n)U'R                  S>/ 5      n*U*(       a  SCU*S    S3U*S    SD3OS&n+U$R+                  SEU% SFU( SGU) SHU+ SI3	5        M     SJR1                  U$5      U!SK'   GO*UR7                  5       n,U, Hp  n-U-R                  S)5      U:X  d  M  U-R                  S:S;5      U!S:'   U-R                  S<S;5      U!S='   U-R                  S>S?S@/5      U!S>'   U-R                  SASB5      U!SA'     O   U,(       a  / n$U, H  n-U-R                  S)S&5      n.U-R                  S<S5      n(U-R                  S:S5      n)U-R                  S>/ 5      n*U*(       a  SCU*S    S3U*S    SD3OS&n+U$R+                  SEU. SFU( SGU) SHU+ SI3	5        M     SJR1                  U$5      U!SK'   UR9                  5       n/S	S
SSS.nUR                  US	5      nU/(       a:  UU/;   a4  SSLKJn0  U0R?                  U/U   UUU5      n1U R                  SMSNU SO35        O/U R                  SMSP5        U(       a  UOSn2URA                  UUU!U2SQ9n1U1(       a(  UU l!        U R                  SMSR[        U5       SS35        U1$ U R                  SST5        g!    GN:= f! [&         aJ  nU R                  SSU S [)        U5       35        UR                  S!S"5      (       d   SnAGMG   SnAG
N6SnAff = f! [&         aJ  nU R                  SSU S [)        U5       35        UR                  S!S"5      (       d   SnAG	M@   SnAGN/SnAff = f! [&         aL  nU R                  SUSV[)        U5       35        SSK"n3U R                  SU3RG                  5       5         SnAgSnAff = f)WuI  从数据库加载并编译 Prompt

Args:
    category_id: 方向ID
    difficulty: 难度（中文：入门/简单/中等/困难）
    language: 编程语言
    vulnerabilities: 漏洞列表
    scene: 场景
    form_data: 表单数据
    
Returns:
    编译后的完整 Prompt 字符串，如果加载失败则返回 None
r   r  )StagePromptGenerator)has_app_contextcurrent_appr2   u7   不在 Flask 应用上下文中，无法访问数据库Nu   方向配置不存在: beginnereasymediumhard)r  r  u   中等u   困难T)include_configadvanced_configr#   r	   	conditionknowledge_count>r   r'  r   u    不满足条件 u	   ，跳过z>=<z<=z==u   解析阶段条件失败: u
   , 错误: requiredFrq   user_extensionz

rB   skip_forbiddenr0   rl   u#   ) 没有内容且非必需，跳过u   方向 u    没有配置阶段difficulty_configdescriptionoutput_formatpromptsr   knowledge_script_instructionr  available_languageszPHP, Python, Node.js, Go, Javaflag_formatzDASCTF{...})rN  r   r   knowledge_pointsr   r  r  r  writeup_countr*  	max_countmax_knowledgedepth_rangeg      ?g      $@	diff_rateg333333?r   ]z| z | u    个 | u    篇 | z |r   difficulty_table)PromptCompilerServicer.   u:   已从数据库加载已编译的 Prompt 模板（难度: u   ）uA   数据库中未找到已编译的 Prompt 模板，重新编译...)r   stagescontextglobal_rulesu   已加载 Prompt，包含 r  u#   从数据库加载的 Prompt 为空r4   u"   从数据库加载 Prompt 失败: )$r;  r  ,app.services.category.stage_prompt_generatorr  flaskr  r  r9   r<  r   to_dictr   r7  get_stages_by_difficultyr>  rt   r  rG  r@  r<   r=   r   
get_stagesrl   r?  get_difficultiesitemsget_difficulty_rulesget_compiled_prompts-app.services.category.prompt_compiler_servicer  replace_placeholderscompile_full_promptr'   	traceback
format_exc)4r(   r   r   r   r   r   r   r  r  r  r  rN  difficulty_mapdifficulty_keyr#   config_dictr  r  merged_stagesr   
stage_copyr  	thresholdr?   prompt_contenthas_contentis_required
all_stagesdiff_configr  prompt_dataknowledge_instructionscript_instructionr  difficultiesr  difficulty_table_rows	diff_namediff_cfg
diff_rulesr  r  r  	depth_strdifficulty_rulesrulerl   compiled_promptsr  compiled_promptr  r  s4                                                       r)   r:  $AIService._load_prompt_from_database  sP   j	AY: #$$		)%^_%++//<H		)'>{m%LM % " 	N ,//
JGN !M&..d.C$3
;O`Cacg8h8h$/0A$B$F$F$WM 66zBF6@RV6W6Wc/2]^OM#E!*EJ !&		+ 6I )0I=#&)#303IOOC4H4K4Q4Q4S0TI,;i,G(,		'WUYYt_DUUfgpfqqz;{(|(0 -H &*Y%603IOOD4I!4L4R4R4T0UI,;y,H(,		'WUYYt_DUUfgpfqqz;{(|(0 -I &)I%503IOOC4H4K4Q4Q4S0TI,;i,G(,		'WUYYt_DUUfgpfqqz;{(|(0 -H &*Y%603IOOD4I!4L4R4R4T0UI,;y,H(,		'WUYYt_DUUfgpfqqz;{(|(0 -I &*Y%603IOOD4I!4L4R4R4T0UI,;y,H(,		'WUYYt_DUUfgpfqqz;{(|(0 yy**).x%>>*:;;;EFV;WZ`;`cq;qJ'78;IJ'78 #;AAC E"'7<BBD  
 '&0nnZ&G&r:>>ZjlqKr* IIg9M8NbQ[Q_Q_`fQgPh  iL  0M  N$!((4u $z &002
!IIi7;-?R)ST'E!*EJ !&		+ 6I )0I=#&)#303IOOC4H4K4Q4Q4S0TI,;i,G(,		'WUYYt_DUUfgpfqqz;{(|(0 -H &*Y%603IOOD4I!4L4R4R4T0UI,;y,H(,		'WUYYt_DUUfgpfqqz;{(|(0 -I &)I%503IOOC4H4K4Q4Q4S0TI,;i,G(,		'WUYYt_DUUfgpfqqz;{(|(0 -H &*Y%603IOOD4I!4L4R4R4T0UI,;y,H(,		'WUYYt_DUUfgpfqqz;{(|(0 -I &*Y%603IOOD4I!4L4R4R4T0UI,;y,H(,		'WUYYt_DUUfgpfqqz;{(|(0 yy!455.EReLf:f&+,?&@&P&??6221<V1DJv.&??=9E8CM8RJ}5&???;;:Eo:VJ7&???;;:Eo:VJ7&??+;<<;FGW;XJ'78 $ii	26G!'400Z75J&-j&9&:k4+H+H-8__Y-KN-#->>2B#C#CCMN^C_bhChkyCyJ/?$@CQJ/?$@ -1)yy!455.EReLf:f&+,?&@&P0;@^0_-005		:X0Y-,1F1L1L1N1N-B-H-H-J*%>>*:;;;EFV;WZ`;`cu;uJ'78;MJ'78 #;AAC E"'7<BBD  
 '&0nnZ&G&r:>>ZjlqKr* IIg9M8NbQ[Q_Q_`fQgPh  iL  0M  N$!((4w (~ %MM($BL_^bBcBcDIIo$>ix.8.E.E6*5'0}}5JLl'm(}}]MJG $446L
l :$Z044WbA+099_a+H(+099[!+D().=3+)N&',yyc'B$ )+%+7+=+=+?'Ix!)gr!:J *{A >I$.NN?A$FM",.."CKKV!KN#32k!n5EQ G\^I)002i[I;gVcUddklukvvx1yz ,@ /3ii8M.N*+ $,#@#@#B ,Dxx':53788OQ3O03788K3K015-#t1U./3xxS/I, - $,.) 0#xx3$(HH[!$<	(,!(D&*hh}b&AOZaA'7r+a.9I$K`b	-44r$s9+WUbTccjktjuuw5xy !1 37))<Q2RG./  (<<>$ " 	N ,//
JGNN6F$F_"7"L"L$^4#	# 		&$^_i^jjm"no 		&$eg0=}4"6"J"J +(#!-	 #K # (5%		&$>s=?Q>RR\"]^&&		)%JKMV  ) ) IIi3Mi[Xbcfghcibj1kl#(99Z#?#? ( $@)D  ) ) IIi3Mi[Xbcfghcibj1kl#(99Z#?#? ( $@)t  	IIg!CCF8LMIIgy3356		s  2v5 7v5 -v5 	As? 
A v5 +A&tv5 At4v5 8Atv5 At:v5 >AtEv5 %#v5 	A&u/v5 3Auv5 Au5v5 9Auv5 Au;R'v5 &Gv5 ,v5 ?tv5 
u8u	v5 uv5 
v2(8v- v5 -v22v5 5
x?Axx)r'   r   r$   r&   r   r"   r   r   r   r%   r#   r    r   )NNNN)rB   )T
   )rB   webN)+__name__
__module____qualname____firstlineno____doc__r  r=   r   r*   r   r!   r9   r8   rK   rc   boolrh   r   r   ro   ru   r   r   r   r   r   r   r   r   r   r   r   r6  rB  rD  rF  r   rH  r  r   rA  r:  __static_attributes__ r,   r)   r   r      sg    !%&*3939 39 	39
 $39 39j!!
F+# + +2c 2C 2.# . .> >c >C >
)d )	4S> 	N NIc I 3S 3 4S> 	^# 	^ 	^3s 3_ _M4: Mc MdSWj M^d x} B #%	@@ @ !	@
 
c3h@Dh
s h
T#Y h
WZ h
hk h
  BE h
  Y\ h
  qu  vy  {~  v~  q h
  KO  PS  UX  PX  KY h
T3S 3Xc] 3B# B(3- Bd x} B$ $ $$HSM s x} C HSM cC c cs cyc ys yVY y48IyFIyVZ[^`c[cVdyiqruivyr,   r   r   re   c                     [        SSU 0UD6$ )u   创建 AI 服务实例的便捷函数

Args:
    user_id: 用户 ID
    **kwargs: 其他参数传递给 AIService
    
Returns:
    AIService 实例
r   r  )r   )r   kwargss     r)   create_ai_servicer    s     /W///r,   c                       \ rS rSrSrSS\S\S\4S jjrS\S	\4S
 jr	S r
S rS\4S jrS rS rS\4S jrS\S\\\4   4S jrS\4S jrS\\\\4      4S jrSrg)ContinueConversationServicei+  uC   继续对话服务

支持任意 AI 提供商的继续对话功能
Nr   workspace_dirr   c                     Xl         [        U5      U l        X0l        S U l        S U l        / U l        U R                  5         U R                  5         U R                  5         g N)
r   r   r  r   r   r    r"   r   r!   _load_conversation_history)r(   r   r  r   s       r)   r*   $ContinueConversationService.__init__1  sT    !-0(2659.0  "'')r,   rP   rQ   c                     U R                   (       a  U R                  X5        [        [        U[        R                  5      nU" SU 35        g )Nz[ContinueConversation] rS   rV   s       r)   r9    ContinueConversationService._log<  s;    e-65&++6*7)45r,   c                 b    [         R                  " U R                  5      U l        U R                  (       a*  U R	                  SSU R                  R
                   35        g U R	                  SS5        g ! [         a/  nU R	                  SS[        U5       35        S U l         S nAg S nAff = f)Nr.   r/   r2   r3   r4   r5   )r
   r6   r   r   r9   r:   r<   r=   r>   s     r)   r   *ContinueConversationService._init_providerB  s    	!-==dllKDM}}		&$?@[@[?\"]^		)%CD 	!IIg!?AxHI DMM	!s   AA5 "A5 5
B.?%B))B.c                 ~   ^  [         R                  " [        T R                  5      5      n[	        UU 4S jS9T l        g )Nc                 .   > TR                  U SU 35      $ )Nr^   rZ   )rP   r   r(   s     r)   <lambda>AContinueConversationService._init_tool_executor.<locals>.<lambda>Q  s    DIIewse_,Mr,   )rD   r   )r   rF   r=   r  r   r    )r(   rD   s   ` r)   r!   /ContinueConversationService._init_tool_executorM  s1    99#d>P>P:QR)M
r,   re   c                      U R                   S-  $ )Nz.conversation_history.jsonr  rg   s    r)   _get_history_file-ContinueConversationService._get_history_fileT  s    !!$@@@r,   c                    U R                  5       nUR                  5       (       al   [        USSS9 n[        R                  " U5      nUR                  S/ 5      U l        U R                  SS[        U R                  5       S35        S S S 5        g / U l        g ! , (       d  f       g = f! [         a&  nU R                  SS	U 35        / U l         S nAg S nAff = f)
Nrry   rz   r"   r.   u
   已加载 u    条历史消息r2   u   加载对话历史失败: )
r  rJ   r   r   loadr   r"   r9   rt   r<   )r(   history_filer  datar?   s        r)   r  6ContinueConversationService._load_conversation_historyW  s    --/  #,g>!99Q<D$(HHZ$<DMIIf
3t}}3E2FFV&WX ?> DM ?>  #		)'A!%EF "#s5   B+ AB	B+ 
B($B+ (B+ +
C5CCc                    U R                  5       n [        USSS9 n[        R                  " SU R                  0USSS9  S S S 5        g ! , (       d  f       g = f! [
         a  nU R                  SS	U 35         S nAg S nAff = f)
Nwry   rz   r"   Fr2  )ensure_asciiindentr2   u   保存对话历史失败: )r  r   r   dumpr"   r<   r9   )r(   r  r  r?   s       r)   _save_conversation_history6ContinueConversationService._save_conversation_historye  sv    --/	ClC':a		:t}}5quUVW ;:: 	CIIi#=aS!ABB	Cs4   A $A
A 

AA A 
B%A??Bc                 V    SU R                    SU R                    SU R                    S3$ )Nu}   你是一个 CTF 题目完善助手。用户已经生成了一个 CTF 题目，现在需要你帮助完善。

工作目录: u'  

## 工具
- run_command: 执行 shell 命令
- read_file: 读取文件
- write_file: 写入文件
- list_directory: 列出目录内容

## 工作流程（必须遵循）

在优化题目时，你必须按以下流程操作：

1. **先搭建 Docker 环境**：
   - 进入 docker 目录：`cd u   /docker`
   - 构建并启动容器：`docker-compose up -d --build`
   - 检查容器状态：`docker ps`

2. **测试验证**：
   - 检查服务是否正常运行：`curl http://localhost:端口`
   - 运行 exp.py 验证漏洞：`python3 uJ  /exp.py localhost 端口 DASCTF{test12345}`
   - 查看容器日志：`docker-compose logs`

3. **根据测试结果优化**：
   - 如果测试失败，分析错误原因并修复代码
   - 修复后重新构建并测试：`docker-compose down && docker-compose up -d --build`
   - 重复测试直到 exp.py 能成功获取 flag

4. **清理**：
   - 完成后停止容器：`docker-compose down`

## 重要提醒
- 不要只看代码就下结论，必须实际运行测试
- 每次修改代码后都要重新构建 Docker 并测试
- 确保 exp.py 能成功获取 flag 才算完成r  rg   s    r)   _build_system_prompt0ContinueConversationService._build_system_promptm  sI    !!" #! "&!3!3 4 5, -1,>,>+? @2+#5 #	5r,   r]  c           
         U R                   (       d  SSS.$ U R                  (       d,  U R                  R                  SU R                  5       S.5        U R                  R                  SUS.5        [        R
                  " 5       nSnSn[        U5       H  n U R                   R                  U R                  US	9nUR                  SS5      nUR                  S5      n	U(       a  XH-  nSUS.n
U	(       a  XS'   U R                  R                  U
5        U	(       d    OyU	 Hn  nU R                  R                  U5      nU R                  R                  SUR                  SS5      UR                  S0 5      R                  SS5      US.5        Mp     GM     U R                  5         SU[        U R                  5      S.$ ! [         a/  nU R                  S
SU 35        S[        U5      S.s S nAs  $ S nAff = f)NFr   )r   r4   r   r   r      rB   r   r4   r   r   r   r   r   r   r   rl   r   T)r   r   r  )r   r"   r   r$  r   r   r   r   r<   r9   r=   r   r    r   r!  r  )r(   r]  r   rb  full_response_r   r?   r   r   r   r   r   s                r)   continue_conversation1ContinueConversationService.continue_conversation  s   }}$/GHH}}MM  (t?X?X?Z![\f9IJK,,.~&A;==--dmm5-I
 ll9b1G!l3J(%0WEM.8l+MM  /'	"00BB9M$$"$-MM$$;%MM*b9==fbI*	&  (+ '< 	'') % !3!34
 	
;  ;		'%6qc#:;#(3q6::;s   $G
G;"G6.G;6G;c           	   #     #    U R                   (       d  Sv   g U R                  R                  SUS.5        [        U R                   S5      (       a  Sn U R                   R	                  U R                  S [        U R                  5      S9 H  nUR                  S5      nUS:X  a  UR                  SS5      nX%-  nUv   M6  US	:X  a  UR                  S
S5      nSU S3v   MX  US:X  a  SUR                  SS5       S3v   Mx  US:X  d  M  M     U(       a  U R                  R                  SUS.5        GO[        S U R                   5       5      (       d-  U R                  R                  SSU R                  5       S.5        [        R                  " 5       nSn	[        U	5       GHA  n
 U R                   R!                  U R                  U[        U R                  5      S9nUR                  SS5      nUR                  S5      nU(       a  Uv   SUS.nU(       a  XS'   U R                  R                  U5        U(       d    OU H  nUR                  S0 5      R                  S
S5      nSU S3v   U R"                  R%                  U5      nU R                  R                  S	UR                  SS5      UUS.5        ['        U5      S:  a  SUS S  S3v   M  SU S3v   M     GMD     U R)                  5         g ! [         a/  nU R                  SSU 35        S[        U5       3v    S nAg S nAff = f! [         a0  nU R                  SSU 35        S[        U5       3v    S nA  g S nAff = f7f)Nu   [错误] 未配置 AI 提供商r   r   chat_streamrB   )r   r  rk   r   r   rl   u   
🔧 执行工具: r   r4   u   
❌ 错误: rQ   finishr   r   u	   [错误] c              3   H   #    U  H  oR                  S 5      S:H  v   M     g7f)r   r   N)r   ).0ms     r)   	<genexpr>KContinueConversationService.continue_conversation_stream.<locals>.<genexpr>  s     H-QuuV}0-s    "r   r   r'  r   r   r   r   r+  u   ✅ 结果: z...
)r   r"   r   r5  r-  r=   r  r   r<   r9   anyinsertr$  r   r   r   r   r    r   rt   r!  )r(   r]  full_contentchunk
chunk_typer   r   r?   r   rb  r)  r   r   r   r   r   s                   r)   continue_conversation_stream8ContinueConversationService.continue_conversation_stream  s?    }}33 	f9IJK 4==-00L!]]66MM"%d&8&8"9 7 E
 "'6!2J!Y."'))Ir":$/%#v-$)IIfb$9	 5i[CC#w. .uyyB/G.HKK#x/!&  MM((+,)WX H$--HHH$$QdF_F_Fa(bc"002EN>*#}}11$--u\_`d`r`r\s1tH #,,y"5%\\,7
!M)4 I2<,/$$]3!!+I )j" = A A&" MI1)B??"&"4"4"F"Fy"QKMM(( &(1dB(? )#.	*  ;'#- ,[#->,?uEE ,[M<< ",- +P 	'')i  		'%6qc#:;!#a&** ! IIg):1#'>?%c!fX..sc   AM8B4K? )K? 6A6M8-8L;%DM8?
L8	%L3.M83L88M8;
M5%M0*M80M55M8c                 L   / nU R                    H  nUR                  S5      S:X  a&  UR                  SUR                  SS5      S.5        M>  UR                  S5      S:X  d  MU  UR                  S5      (       d  Mm  UR                  SUR                  SS5      S.5        M     U$ )Nr   r   r   rB   r   r   )r"   r   r   )r(   historyr   s      r)   get_conversation_history4ContinueConversationService.get_conversation_history  s    ==Cwwv&(3779b;QRSK/CGGI4F4F	SU@VWX	 !
 r,   )r   r"   r   r    r   r  r  )r  r  r  r  r  r  r=   r   r*   r9   r   r!   r   r  r  r!  r$  r   r   r*  r9  r   r=  r  r  r,   r)   r  r  +  s    
	* 	*C 	*x 	*6# 6 6	!
A4 AC$5c $5L1
c 1
d38n 1
fW*S W*r$tCH~*> r,   r  )r  osr   loggingr   typingr   r   r   r   r   pathlibr   	providersr
   r   providers.baser   r   r   r   core.stage_detectorr   	getLoggerr  rU   r   r  r  r  r  r,   r)   <module>rG     si    
   	 6 6  8 * . .			8	$D DN0
0s 
0 
0{ {r,   