
    \iw                        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\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S?S(\S)\\   S*\S+\S,\S\S-\\\4   S.\\   S\\\4   4S/ jjrS\S\\   4S0 jr S\S\\   4S1 jr!S"\S\\   4S2 jr"S3\S\4S4 jr#S\\   4S5 jr$S3\S\\   4S6 jr%S7\S\\   4S8 jr&S\S9\S\4S: jr'S\S+\S(\S)\\   S*\S-\\\4   S\\   4S; jr(S<r)g)@	AIService   u`   统一 AI 服务

封装 AI 提供商和工具执行，为题目生成提供完整的 AI 能力
Nuser_id
output_dirlog_callbackcategory_idai_config_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: 日志回调函数
    category_id: 方向 ID（用于设置工作目录）
    ai_config_id: 指定的 AI 配置 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         A   /Users/yu22x/Desktop/ddd_副本138/ctf/app/services/ai/service.py__init__AIService.__init__   s    " $(&( 37 6:  " /1 -1  ',"'
 ;= +- 79    c                     [         R                  " U R                  U R                  S9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 提供商)r   info   已初始化 AI 提供商:  ()warning   未找到可用的 AI 配置error   初始化 AI 提供商失败: N)r
   create_for_userr   r   r   set_log_callback_on_provider_log_logprovider_namemodel	Exceptionstrr(   es     r)   r   AIService._init_providerR   s    		!-==dllY]YjYjkDM}}..t/D/DE		&$?@[@[?\\^_c_l_l_r_r^sst"uv		)%CD 	!IIg!?AxHI DMM	!s   B%B; (B; ;
C4%C//C4c                 \   [         R                  " U R                  (       a  U R                  OSU R                  S9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output_base_dirr   ge10r2   u   方向目录不存在: u   ，使用默认目录: r.   u   工作目录设置为: )sandboxr   working_dir)r   create_for_ctf_generationr   r   r   __file__parentresolver=   existsr9   r   _on_tool_logr    )r(   rE   rF   ctf_dircategory_path	ge10_paths         r)   r!   AIService._init_tool_executor_   s   
  99/3DOOD((
 
 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(   rQ   rR   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(   rQ   rR   s      r)   r8   AIService._on_provider_log   s    		%;wi01r,   c                 .    U R                  USU 35        g)u   工具执行日志回调[Tool] Nr[   r\   s      r)   rL   AIService._on_tool_log   s    		%77),-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;   ri   rc   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(   rm   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   u   提示词文件不存在: r4   u   加载提示词文件失败: N)r   rK   	read_textr#   r9   r<   r=   )r(   rs   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   rc   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） )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   r   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(   rs   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&   rc   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   r   u   
... [已截断，原长度 u    字符]i  |u   
... [已截断]i  u   上下文压缩完成: u    → u
    条消息)rp   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
functionrh   r   	arguments{})
write_filecreate_filery   rs   )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_call5  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   r   r   r   r   r   rh   r.      执行工具: r   idr   tool_call_idrh   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   rp   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.chatS  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_datatask_idc	                 3  ^m^n^o SSK n	SSKn
U R                  (       d  SSS.$ [        U R                  S5      (       a  U R                  R                  S;   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                  R                  UU[        U[        5      (       a  UR                  S5      OUUUUUUS9$ [        [        5      R                  R                  R                  R                  nUS-  nUS-  nUR!                  SS9  U(       aV  SU;   a  UR#                  S5      S   SS OUSS nUSU SU
R                  R%                  5       R'                  S5       S3-  nOFSSKnUSUR*                  " 5        SU
R                  R%                  5       R'                  S5       S3-  n SSKJnJn  U(       a0  U   UU;  a  0 UU'   [3        U5      UU   S'   SUU   S'   SSS5        OSSKJn  [3        U5      US'   SUS'   U R                  S	SU SU S 35        SS#KJnJmm  U" [3        U5      S$5      mnTnR?                  5         U R                  moS%[2        S&[2        4UmUnUo4S' jjnUU l        TnU l         S&[2        4UmUn4S( jjnUU l!        U RE                  XdXX7=(       d    0 5      n SSKJnJn  U RF                  (       a  [I        U RF                  5      OSnUS:  a  U(       at  U   UU;  a  0 UU'   UUU   S)'   S*UU   ;  a  0 UU   S*'   [K        U5       H  nUUU   S*   ;  d  M  S+UU   S*   U'   M     U R                  S	S,U S-U S 35        SSS5        OeSSKJn  UUS)'   S*U;  a  0 US*'   [K        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 RM                  U5        U R                  S	S1[I        U5       S235        O%U R                  SS3U S4U S535        SS6U S4U S53S.$ / nU(       Ga   SS7K'J(n  URR                  R                  U5      nU(       Ga~  URU                  5       nU GHg  n U R                  S85      n!U R                  S9U!5      n"U R                  S:5      n#U R                  S;S5      n$U$(       a  U!S<;   a  MY  UR                  U!5      n%U%b  U%S=:X  a  Mu  Sn&U#S>;   a  [        U%[V        5      (       a]  S?RY                  U% V's/ s H>  n'U'(       d  M  [3        [        U'[        5      (       a  U'R                  SU'5      OU'5      PM@     sn'5      n&GO([        U%[2        5      (       a  U%n&GO[3        U%5      n&GOU#S@:X  a  [        U%[        5      (       a  U%R                  S[3        U%5      5      n&GOU R                  SA/ 5      n(U( H~  n)[        U)[        5      (       a  U)R                  SB5      OU)n*U*U%:X  d  M3  [        U)[        5      (       a+  U)R                  S9U)R                  SB[3        U)5      5      5      O
[3        U)5      n&  O   U&(       d  [3        U%5      n&GO U#SC:X  Ga  [        U%[        5      (       a  U%R                  SD5      (       a  GM,  U%R                  S[3        U%5      5      n+U+(       a  U+R[                  5       SE;   a  GMe  U+(       a  U+R[                  5       (       d  GM  U%R                  SF5      n,U,(       aA  [        U,[        5      (       a$  U,R                  SS=5      n-U-(       a  U+ SGU- 3n&OEU+n&OBU+ SGU, 3n&O:U+n&O7[3        U%5      R[                  5       SE;   a  GM   [3        U%5      n&O[3        U%5      n&U&(       d  GM!  U&R[                  5       (       d  GM9  U&R[                  5       SE;   a  GMP  UR]                  SHU" SIU& 35        GMj     U(       d6  [        U[V        5      (       a  S?RY                  U5      OUn.SKU 3SLU. 3SMU 3/nU(       a7  UR[                  5       (       a"  UR]                  SNUR[                  5        35        SORY                  U5      SO-   n/[        U[V        5      (       a  S?RY                  U5      OUn.U R                  S	SPU SQU SQU. 35        U R                  S	SRU/ 35        Sn0U RF                  (       aO  U RF                  S   n1U1R                  SSS5      n2U R_                  U0STSUU2 SV35        U R_                  U0SWU2 SX35        O&U R_                  SSTSY5        U R_                  SSWSZ5        U0n3Sn4Sn5S[n6Sn7S\n8/ n90 U l0        / U l1        / n:U Rd                  (       a  U:R]                  S]U Rd                  S^.5        U:R]                  S_U/S^.5        [f        Rh                  " 5       n;Sn< Sn=U=U6:  Ga  U=S`-  n=SSaKJ5n>  U>" 5       (       as  U R                  S!Sb5        U RC                  Sc5        U RF                  (       a8  [K        [I        U RF                  5      5       H  n?U R_                  U?SdSe5        M     SSfU5U4Sg.$ [I        U:5      U Rl                  Sh   :  aU  U3U<:  aO  U RC                  Si[I        U:5       Sj35        U Ro                  U:U35      n:U3n<U RC                  Sk[I        U:5       35        U:(       a  U:S   n@U@Sl   S_:X  a`  U RC                  SmU= Sn35        W@So   nA[I        UA5      Sp:  a%  U RC                  WASSp Sq[I        UA5       S23-   5        OU RC                  WA5        O{W@Sl   Sr:X  ar  W@R                  SSs5      nBU@So   nC[I        UC5      St:  a0  U R@                  Rq                  WBWCSSt Sq[I        UC5       S23-   5        OU R@                  Rq                  WBWC5        U R                  Rs                  U:U;Su9nDUDR                  SoS=5      nEUE(       aZ  U RC                  SmU= Sv35        [I        WE5      Sw:  a%  U RC                  WESSw Sq[I        UE5       S23-   5        OU RC                  WE5        U Ru                  WE5      nFSnGUFb  U RF                  (       a{  WFS`-
  nHSUHs=::  a  [I        U RF                  5      :  a  O  OWHnGO]WFS:  aI  U R                  S!SxWF Sy[I        U RF                  5       Sz[I        U RF                  5      S`-
   S{U3 35        SnGOWFS:  a  WFS`-
  OSnGWGcy  U RF                  (       ah  [w        U RF                  5       HO  u  n?nI[3        UIR                  S8S=5      5      nJUIR                  SS=5      nKS|UJ 3WE;   d  S}WJ 3WE;   d  WKWE;   d  MM  U?nG  O   WGGbH  WGU3:w  GaA  WGU3:  a}  U RF                  (       a  U Ry                  U35      O
[3        U35      nLU RF                  (       a  U Ry                  WG5      O
[3        WG5      nMU R                  S!S~U3 SWL SWG SUM S3	5        SnGGO,WGU3:  a  WE(       a  U R{                  U3WE5        [K        U3WG5       H  nNU R_                  UNSWS}UN S35        M     WGn3Sn7U RF                  (       a  U Ry                  U35      O
[3        U35      nJU R}                  UJ5      nKU R_                  U3STSUK 35        U R                  S	SU3 SUJ SUK 35        GOnU7S`-  n7U RF                  (       a  [I        U RF                  5      S`-
  OSnOU7U8:  Ga7  U3WO:  Ga0  U3S`-   nPU R_                  U3SWS}U3 S35        UPn3Sn7U RF                  (       a  U Ry                  U35      O
[3        U35      nJU R}                  UJ5      nKU R_                  U3STSUK 35        U R                  S!SU3 SUJ SUK 35        U RF                  (       a  U3[I        U RF                  5      :  aw  U RF                  U3   nQ[3        UQR                  S8U35      5      nJUQR                  SS}UJ 35      nKSUJ SIUK S3nRU:R]                  S_URS^.5        U RC                  SU3 SUJ SUK S35        U4c/  U R                  WE5      nSUS(       a  WSn4U R                  S	SU4 35        WDR                  S5      (       Ga  U5[I        WDS   5      -  n5U RC                  SmU= S[I        UDS   5       S35        SWEUDS   S.nTU:R]                  UT5        UDS    GH  nUUUS   S   nBUUR                  S0 5      R                  SS5      nV[I        UV5      S:  a$  U R@                  Rq                  WBSWVSS  S35        OU R@                  Rq                  WBSWV 35        U R                  S	SWB 35         SSK@nW[        WV[2        5      (       a  WWR                  " WV5      OWVnXWBS;   a  SWX;   a  WB SWXS    3nYOWBnY U9R]                  WY5        [I        U95      S:  a  U9R                  S5        U4c  U R                  WU5      n4U R                  WU5      nZUZ(       a  U R                  WZ5        U R                  R                  WU5      n[[I        U[5      S:  a0  U R@                  Rq                  WBSW[SS  S[I        U[5       S235        OU R@                  Rq                  WBSW[ 35        U:R]                  SrWUS8   WBW[S.5        GM     U RF                  (       Gaj  U3[I        U RF                  5      S`-
  :  n\U\(       GaG  U4(       Ga?  SS/n][I        U95      S:  Ga+  U9SS n^SU^S   ;   a  W^S   R#                  S5      S   OW^S   n_W^S   U^S`   s=:X  a  W^S   s=:X  a	  W^S   :X  a  O  OW_W];   a  SW^S   ;   a  W^S   R#                  SS`5      S`   OS=n`U`(       a  SW` S 3OS=naU R                  S!SW_ SUa S35        U RC                  SU_ SUa S35        U R_                  U3SWS5        U RF                  (       a8  [K        [I        U RF                  5      5       H  n?U R_                  U?SWS=5        M     U R                  S	S5        SWEU5U4S.$ G
Mb  U R                  5       nbSn\U RF                  (       a  U3[I        U RF                  5      S`-
  :  n\W\(       a  U4(       a  U RF                  (       a  [I        U RF                  5      S`-
  OU3ncU R_                  UcSWS5        U R                  S	S5        U RF                  (       a8  [K        [I        U RF                  5      5       H  n?U R_                  U?SWS=5        M     SWEU5U4S.$ U:R]                  SWES^.5        SndU RF                  (       ag  SSKJn  UR                  S*0 5      neSnf[I        U RF                  5      ng[K        Ug5       H!  n?WeR                  U?5      nhUhSW:X  d  M  WfS`-  nfM#     WfWg:  a  SndWd(       a\  U4(       aU  U R                  S	S5        U R_                  U RF                  (       a  [I        U RF                  5      S`-
  OU3SWS5        SWEU5U4S.$ W\(       Gd;  U RF                  (       Ga)  Wd(       Gd!  SSKJn  UR                  S*0 5      neUeR                  U35      niUiSW:w  a_  U RF                  S   nj[3        UjR                  S8S=5      5      nbUjR                  SS5      nkSU3 SUb SUk S3nlU:R]                  S_UlS^.5        GM  U3[I        U RF                  5      S`-
  :  aw  U3S`-  n3U RF                  (       a  U Ry                  U35      O
[3        U35      nJU R}                  UJ5      nKU R_                  U3STSUK 35        U R                  S	SU3 SUJ SUK 35        GM  U4c  U:R]                  S_SS^.5        GM   U R                  S!SU6 35        U4(       a  U RF                  (       a9  [K        [I        U RF                  5      5       H  n?U R_                  U?SWS=5        M     O]U RF                  (       a9  [K        [I        U RF                  5      5       H  n?U R_                  U?SWS=5        M     OU R_                  U3SWS=5        SSU5U4SS.$ SSU6 S3U5S.$ ! , (       d  f       GN6= f! [6         a   nU R                  S!S"U 35         SnAGNESnAff = f! , (       d  f       GN= f! [6         a   nU R                  S!S0U 35         SnAGNSnAff = fs  sn'f ! [6         aT  nU R                  S!SJU 35        SKU 3SL[        U[V        5      (       a  S?RY                  U5      OU 3SMU 3/n SnAGN8SnAff = f!   WBnY GN= f! [6         a:  nU R                  SS[3        U5       35        SS[3        U5       3U5S.s SnA$ SnAff = f)u6  生成 CTF 题目（模拟 Augment 八轮流程）

使用预设的提示词和工具，生成完整的 CTF 题目
实现分阶段执行和验证，确保题目质量
Args:
    language: 编程语言
    vulnerabilities: 漏洞类型列表
    scene: 场景
    difficulty: 难度（中文：入门/简单/中等/困难）
    extra_requirements: 用户额外要求
    category_id: 方向ID（如 'web'）
    form_data: 表单数据（可选）
    task_id: 任务ID（可选，用于创建独立工作目录避免多任务冲突）
    
Returns:
    生成结果
r   Nr4      未配置 AI 提供商)statusrR   rj   )	anyrouteragentrouteraugmentr:   r.   u
   检测到 u$    提供商，使用 CLI 模式生成r7   rh   )r   r   r   r   r   r   r   r   rD   logsT)exist_ok-r      ai_service__z%Y%m%d_%H%M%Sz.txt)generation_statusesgeneration_locklog_filelog_position)generation_statusu   日志文件: z (task_id: r1   r2   u   设置日志文件失败: )UnifiedLogWriterLogLevelr   rQ   rR   c                 "  > TR                   TR                  TR                  TR                  TR                  TR                  S.nUR                  U R                  5       TR                  5      nTR                  XS9  T(       a	  T" X5        g g )N)r   r.   r2   warnr4   r   rQ   )DEBUGINFOWARNINGERRORSUCCESSr   lowerwrite)rQ   rR   	level_map	log_levelr   
log_writeroriginal_log_callbacks       r)   enhanced_log_callback?AIService.generate_ctf_challenge.<locals>.enhanced_log_callback1  sy     " #++ ((!#++I "ekkmX]]CIW6$%e5 %r,   c                 "  > TR                   nU nU R                  S5      (       a  U SS nSU ;   a  TR                  nOSU ;   a  TR                  nOSU ;   a#  SU ;   a  TR                   nTR                  5         OxSU ;   a#  SU ;   a  TR                   nTR                  5         OOSU ;   a  S	U ;   a  TR                  nO6S
U ;   d  SU ;   d  SU ;   a  TR                  nOSU ;   a  TR                  5         gTR                  UR                  5       US9  g)u-   写入日志到文件（使用统一格式）
r	   Nu   [上下文管理]u   [系统]u   [轮次   ] 发送给 AI 的消息:   ] AI 响应:u   ] 工具执行结果u   工具:u   参数:u   结果:z<============================================================r   )r   
startswithSYSTEMwrite_separatorTOOLr  strip)rR   rQ   clean_messager   r  s      r)   write_to_log6AIService.generate_ctf_challenge.<locals>.write_to_logD  s    MME#M !!$'' '"g- w& g%*E*P **,g%.G*C **,g%*@G*K g%g)=gAU W$**,]002%@r,   total_stagesstep_statuseswaitingu
   初始化 u    个阶段 (task_id: u"    个阶段（向后兼容模式）u<   未找到阶段配置，阶段状态将由配置动态决定u   初始化阶段状态失败: u$   已从数据库加载系统 Prompt (ro   u   数据库中未找到方向 u    难度 u1    的 Prompt 配置，请先在后台配置 Promptu   未找到方向 CategoryConfigr   labelrg   visible)r   r   )multi_selectmulti_select_categorized, selectoptionsvalueselect_with_subno_scene)u	   无场景u   无特定场景noneNoner   	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	   )is_generation_cancelledu*   检测到生成取消请求，停止生成u3   [系统] 检测到生成取消请求，停止生成	cancelledu   用户取消u   生成已取消)r   rR   r   r   r   u   [上下文管理] 消息数 u    达到阈值，触发压缩...u&   [上下文管理] 压缩后消息数: r   u   [轮次 r  r   i  u   
... (截断，共 r   unknowni  r   r  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   ... (截断)r   )list_directory	read_filery   :   u   结果: u   ... (截断，共 r   r6  r7           u
    (路径: u"   检测到重复执行只读工具 u    4次u   ，在最后阶段强制停止u+   [系统] 检测到重复执行只读工具 u   ，强制停止循环执行u$   检测到循环执行，强制完成u   题目生成完成!r   )r   r   r   r   Fu   题目生成完成u-   检测到所有阶段已完成，返回结果u   成品输出u"   请继续执行，当前在阶段 u   ，需要完成到阶段 u   ）。u   自动推进到阶段 uf   请创建输出目录并生成题目文件。输出目录格式：output/YYYYMMDD_HHMMSS_题目名称/u   达到最大迭代次数: u-   达到最大迭代次数，但生成已完成u   达到最大迭代次数)r   r   r   r   r2   u   达到最大迭代次数 (u   )，生成未完成)r   rR   r   u   生成失败: )I
subprocessdatetimer   hasattrrj   rU   r9   r7   r   generate_ctf_challenger   dictr   r   rH   rI   mkdirsplitnowstrftimeosgetpidapp.routes.generator.utilsr   r   r=   r   r<   "app.services.ai.core.log_formatterr   r   	__enter___log_writer_write_to_log_load_prompt_from_databaser'   rp   r   rq   app.models.database.modelsr  queryget_form_fieldslistjoinr  r   _update_stage_progressr%   r&   r#   r   r   r.  r$   r   
write_toolr   _detect_stage	enumerater   r   r   _detect_output_dirr   r   pop_detect_output_dir_from_toolr   r   r    r   _get_last_stage_id)pr(   r   r   r   r   r   r   r   r   r>  r?  r:   project_rootge10_dirlog_dirtask_suffixr   rG  r   r   r   r?   r   r
  r  r#   r  r   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   r.  idxlast_msgmsg_contentr   tool_contentr   r   new_stage_num	new_stagestage_indexr   r   r   current_stage_idnew_stage_idsmax_stage_index
next_stagestage_config
prompt_msgdetected_dirr   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_countr   current_statuslast_stage_configlast_stage_namecontinue_msgr   r  r	  sp                                                                                                                @@@r)   rA   AIService.generate_ctf_challenge  s   $ 	}}!3  4==/22t}}7R7RV}7}#DMM?DMMD_D_`MIIf
=/9]^_t}}&899..t/@/@A==77! /+5eT+B+Beii'%#5'# 8 	 	 H~,,33::AA&('t$ 8;w'--,R0!4GTVUVKK;{m1X=N=N=R=R=T=]=]^m=n<oos!ttH ;ryy{m1X=N=N=R=R=T=]=]^m=n<oos!ttH	CW$&9979+G4?B8}'0<CD'0@	 %_ I03H!*-45!.1IIfxjG9ANO
 	R &c(m[A
 !% 1 1	6 	6s 	6 	6 2%	A# 	A 	A< * 77QYlq  tC  AC  D"	FW9=9N9N3t445TULa("*==;=/8GS+G4^D +2Eg2NNLN/8I "'|!4A (;G(D_(UUS\ 3G <_ Ma P "5 		&J|nDYZaYbbc*de )" M8D%n5&.??=?)/:"<0$5o$FFDM-o>qA 1 IIf
<.@b&cd		)%cd ""=1IIf DSEWDXX`ab IIg!=k](S]R^  _P   Q  R!-k](:,N  A  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 ,,. !P	In,Q	 O*,,IIi)UV&&'\],,#(T-B-B)C#DC 77[.Y $E #*#4,<&0	  MT%8%89M%NN!$77&&)Ec(m_Ts'tu#66xOH*7'&&)OPST\P]'_` '|H'61**Xi[@Y+Z[&.y&9{+d2 ..{5D/AFZ[^_j[kZlltDu/uv ..{;!&)V3$,LL$C	'/	':|,t3 ,,77	<PUQUCV[ops  uA  qB  pC  CK  ZL  DL  M ,,77	<P  ==--he-D",,y"5 &&)L'IJ7|e+**76E??STWX_T`Saai=j+jk**73 !% 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 ..1PQ^P__bckbllnoynz  {S  0T  U %#'#:#:7#CL#%1
		&,CJ<*PQ <<--$H\,B(CC$ &&)<NsS[\hSiOjNkkv'wx !,#*&.|&<%M
 OOM2 &.l%;	$-j$9&$A	$-MM*b$A$E$EkSW$X	 y>C/ ,,77	XiX\Y\oM^^jCkl ,,77	Xi[CYZ		&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 ,,77	XkZ^[^N_M``rsv  xC  tD  sE  EM  DN  O ,,77	Xk]C[\ !$*,5dO$-'2	) e &<x ,,,)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$($6$69deodppuv~u  @[  8\  %]$($?$?{  ]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 Q %_  	CIIi#=aS!ABB	CV )6  	FIIi#@!DEE	F\ =L~  		)'PQRPS%TU!*.'jQ`bfFgFg		/(Bm|'}~'z2%!V6,5MF  	IIgAx89!+CF84$4 	s  Ab# #%Ab;Ab# ?Ac" =Ac(Ac8Ac" +Ac" 0"Ac" Ac" CAd *Ad
96Ad
/B*Ad FAd *Ad 3Ad BAe? 0LAe? O2Ae? F6AAe5G9Ae? G:Ae5G<JAe? Q>C.Ae? U-A9Ae? W*A3Ae? YH(Ae? b	Ae? b
Ab bAb# b#
Acb-AccAcc
AccAc" cAc" c"
Adc,AddAddAd d
Ae2dA	Ae-e-Ae2e5Ae<e9Ae? e?
Agf	/Af>f8Agf>Agc                 .    [         R                  " U5      $ )u?   从 AI 输出中检测当前阶段（委托给 StageDetector）)r   detect_stage)r(   r   s     r)   rV  AIService._detect_stage  s    ))'22r,   c                     [        [        5      R                  R                  R                  R                  n[        US-  5      n[        R
                  " X5      $ )u;   从内容中检测输出目录（委托给 StageDetector）rD   )r   rH   rI   r=   r   detect_output_dir)r(   r   r\  r]  s       r)   rX  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	-  n
U
R                  5        Hh  nUR                  5       (       d  M  UR                  R                  S
5      (       a  M<  US-  U-  nUR                  5       (       d  M[  [	        U5      s  s  $    M     g!    g= f)u{   从工具调用中检测输出目录

Args:
    tool_call: 工具调用信息
    
Returns:
    输出目录路径或 None
r   Nr   r   r   )ry   rs   	directoryr   z/(?:ge10/[^/]+/)?output/(\d{8}_\d{6}_[^/\s"\']+)r	   rD   .output)r   r   r   r   r=   r   r   r   r   rH   rI   iterdiris_dirrh   r  rK   )r(   r   r   r   r   keyr$  r   dir_namer\  r]  category_dir	full_paths                r)   rZ  &AIService._detect_output_dir_from_tool  s)    		==R044[$GD$$$zz$' E; IEII&XZ]^cZdeEu#(;;q>'+H~'<'<'C'C'J'J'Q'Q#/&#8,4,<,<,>L+2244\=N=N=Y=YZ]=^=^,88,Ch,N	#,#3#3#5#5+.y>$9	 -? E$ 	s1   AE %E A3E ?E !E  E E Er   c                    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                  " X0R                   5      $  SU 3$ !    N	= f)uP   获取阶段名称（优先从配置中获取，否则委托给 StageDetector）r   r   rh   r1  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@U@UVV & 
##	s   %AC   Cc                 z    U R                   (       a*  U R                   S   n[        UR                  SS5      5      $ g)u'   获取配置中的最后一个阶段 IDr   r   r   N)r'   r=   r   )r(   
last_stages     r)   r[  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   r   )r'   rW  r=   r   )r(   r   rz  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   r   N)r'   rp   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,   r   c                     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   r1  r2  r!  r3  r*  N)r'   r   r=   r   r9   )r(   r   r   rR   r   r   s         r)   rT   AIService._update_stage_progress'  se     :>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)u   入门u   简单u   中等u   困难T)include_configadvanced_configr#   r	   	conditionknowledge_count>r   r1  r   u    不满足条件 u	   ，跳过z>=<z<=z==u   解析阶段条件失败: u
   , 错误: requiredFrm   user_extensionz

r   skip_forbiddenr0   rh   u#   ) 没有内容且非必需，跳过u   方向 u    没有配置阶段difficulty_configdescriptionoutput_formatpromptsr   knowledge_script_instructionr!  available_languageszPHP, Python, Node.js, Go, Javaflag_formatzDASCTF{...})ra  r   r   knowledge_pointsr   r  r  ruleswriteup_countr4  	max_countmax_knowledgedepth_rangeg      ?g      $@	diff_rateg333333?[]z| z | u    个 | u    篇 | z |r  difficulty_table)PromptCompilerServicer.   u:   已从数据库加载已编译的 Prompt 模板（难度: u   ）uA   数据库中未找到已编译的 Prompt 模板，重新编译...)r   stagescontextglobal_rulesu   已加载 Prompt，包含 u
    个阶段u#   从数据库加载的 Prompt 为空r4   u"   从数据库加载 Prompt 失败: )$rO  r  app.services.prompt.generatorr  flaskr  r  r9   rP  r   to_dictr   rB  get_stages_by_difficultyrR  rp   r  rD  r  r<   r=   r   
get_stagesrh   rS  get_difficultiesitemsget_difficulty_rulesget_compiled_prompts$app.services.prompt.compiler_servicer  replace_placeholderscompile_full_promptr'   	traceback
format_exc)4r(   r   r   r   r   r   r   r  r  r  r  ra  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rulerh   compiled_promptsr  compiled_promptr  r  s4                                                       r)   rN  $AIService._load_prompt_from_database4  sP   j	AJ: #$$		)%^_%++//<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V"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'   rL  rM  r   r   r$   r&   r   r"   r   r   r%   r#   r    r   )NNNN)T
   )r   webNN)*__name__
__module____qualname____firstlineno____doc__r  r=   r   r   r*   r   r!   r9   r8   rL   boolrd   r   r   rk   rq   rz   r}   r   r   r   r   r   r   r   r   rA  rV  rX  rZ  r   r[  r  r   rT  rN  __static_attributes__ r,   r)   r   r      sl    !%&*3939 39 	39
 39 sm39j!$
L+# + +2c 2C 2.# . .
)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ws wT#Y wWZ whk w  BE w  Y\ w  qu  vy  {~  v~  q w  QY  Z]  Q^ w  jn  or  tw  ow  jx wr3S 3Xc] 3B# B(3- B$d $x} $L$ $ $&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   ra   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  p  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__  sT    !-0(2659.0  "'')r,   rQ   rR   c                     U R                   (       a  U R                  X5        [        [        U[        R                  5      nU" SU 35        g )Nz[ContinueConversation] rT   rW   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_provider  s    	!-==dllKDM}}		&$?@[@[?\"]^		)%CD 	!IIg!?AxHI DMM	!s   AA5 "A5 5
B.?%B))B.c                 |   ^  [         R                  " [        T R                  5      S S9n[	        UU 4S jS9T l        g )NrB   c                 .   > TR                  U SU 35      $ )Nr_   r[   )rQ   r   r(   s     r)   <lambda>AContinueConversationService._init_tool_executor.<locals>.<lambda>  s    DIIewse_,Mr,   )rE   r   )r   rG   r=   r  r   r    )r(   rE   s   ` r)   r!   /ContinueConversationService._init_tool_executor  s;      99 2 23
 *M
r,   ra   c                      U R                   S-  $ )Nz.conversation_history.jsonr  rc   s    r)   _get_history_file-ContinueConversationService._get_history_file  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rru   rv   r"   r.   u
   已加载 u    条历史消息r2   u   加载对话历史失败: )
r,  rK   openr   loadr   r"   r9   rp   r<   )r(   history_filefdatar?   s        r)   r  6ContinueConversationService._load_conversation_history  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wru   rv   r"   Fr<  )ensure_asciiindentr2   u   保存对话历史失败: )r,  r0  r   dumpr"   r<   r9   )r(   r2  r3  r?   s       r)   _save_conversation_history6ContinueConversationService._save_conversation_history  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+  rc   s    r)   _build_system_prompt0ContinueConversationService._build_system_prompt  sI    !!" #! "&!3!3 4 5, -1,>,>+? @2+#5 #	5r,   rp  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      r   r   r4   r   r   r   r   r   r   r   rh   r   T)r   r   r  )r   r"   r   r>  r   r   r   r   r<   r9   r=   r   r    r   r;  r  )r(   rp  r   ru  full_responser   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_streamr   )r   r  rg   r   r   rh   u   
🔧 执行工具: r  r4   u   
❌ 错误: rR   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>F  s     H-QuuV}0-s    "r   r   rA  r   r   r   r   r5  u   ✅ 结果: z...
)r   r"   r   r@  rF  r=   r  r   r<   r9   anyinsertr>  r   r   r   r   r    r   rp   r;  )r(   rp  full_contentchunk
chunk_typer   r   r?   r   ru  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   r   r   r   )r"   r   r   )r(   historyr   s      r)   get_conversation_history4ContinueConversationService.get_conversation_historyv  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   rC  rR  r   rV  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  rG  r   loggingr   typingr   r   r   r   r   pathlibr   	providersr
   r   providers.baser   r   r   r   core.stage_detectorr   	getLoggerr  rV   r   r  r  r  r  r,   r)   <module>r_     si    
   	 6 6  8 * . .			8	$V Vr2
0s 
0 
0@ @r,   