
    ^iJ                        S r SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKJ	r	J
r
JrJrJr  SSKJr  SSKJr  SSKJr  SSKJr   " S	 S
5      rg)u}   
Augment CLI 服务适配器

这个模块提供了与 Augment CLI 的集成，使其能够像 OpenAI API 一样被调用。
    N)DictListAnyOptionalUnionPath   )StageDetector)InstructionBuilder)GuidelineManagerc                      \ rS rSrSrSFS\\   S\\   S\S\\   4S jjr	S	 r
S
 rSGS\\   4S jjrS\S\4S jr    SHS\S\\   S\\\\\4   4   S\S\S\S\\\\4      S\\   S\\\4   4S jjr    SIS\\\\4      S\S\S\\   S\S\\\4   4S jjrS\4S jrS\S\S\S\\   S\S\4S  jr   SJS\S\\   S\S\S\S\S\\\\4      S\4S! jjrS"\S\\   4S# jrS"\S\4S$ jrS%\S&\S\\   4S' jrS\S\S\\   4S( jrSKS\S\\   4S) jjrS*\S+\SS4S, jrS-\SS4S. jr SLS/\S\S\\   S\4S0 jjr!S1\S-\S\\\4   4S2 jr"SKS3\S\4S4 jjr#S/\S\$\\\   4   4S5 jr% SGS1\S3\S6\S7\\   S\\\4   4
S8 jjr& SGS1\S3\S6\S7\\   4S9 jjr'S:\S\4S; jr(S<\S\4S= jr)S<\S\\   4S> jr*S?\S7\S@\SA\SS4
SB jr+ SGS/\S3\S7\\   S\\\4   4SC jjr, SGS/\S3\S7\\   4SD jjr-SEr.g)MAugmentService   u   Augment CLI 服务适配器N	node_pathuser_idverbosemodelc                    U=(       d     [         R                  R                  SS5      U l        [	        [
        5      R                  R                  R                  R                  R                  U l        U R                  S-  U l        U R                  R                  5       (       d  [        SU R                   35      eX l        SU l        SU l        U=(       d    SU l        SU l        SU l        SU l        SU l        X0l        SU l        S	SKnUR-                  [.        5      U l        U R0                  R3                  S
5        g)uF  初始化 Augment 服务

Args:
    node_path: Node.js 可执行文件路径，如果不提供则使用默认路径
    user_id: 用户ID，用于获取用户的Augment Token
    verbose: 是否显示详细输出（默认 False，只显示关键信息）
    model: 模型ID（可选），如果不提供则使用默认模型
	NODE_PATHz%$HOME/.nvm/versions/node/v22.13.1/binge10u   ge10 目录不存在: augmentzAugment CLINFr   u   Augment 服务初始化完成)osenvirongetr   r	   __file__parentproject_rootge10_direxists	Exceptionr   provider_typeprovider_namer   base_urllog_callbacktimeout_recoveredtimeout_warningr   task_idlogging	getLogger__name__loggerinfo)selfr   r   r   r   kwargsr)   s          C/Users/yu22x/Desktop/ge/ctf/app/services/ai/core/augment_service.py__init__AugmentService.__init__   s    # 
bjjnn3'
 !N1188??FFMM ))F2}}##%%4T]]ODEE  '*'i
 ! "'#   	''1 	89    c                     [         R                  R                  5       nU R                   SUR	                  SS5       3US'   [
        R                  " SS/SSUSS9nUR                  S	:w  a  [        S
UR                   35      e[        SUR                  R                  5        35        g! [         a    [        S5      e[
        R                   a    [        S5      e[         a  n[        S[        U5       35      eSnAff = f)u   验证 Augment CLI 是否可用:PATH auggiez	--versionT
   )capture_outputtextenvtimeoutr   u   Augment CLI 不可用: u   ✅ Augment CLI 版本: u9   未找到 auggie 命令，请确保 Augment CLI 已安装u   Augment CLI 验证超时u   Augment CLI 验证失败: N)r   r   copyr   r   
subprocessrun
returncoder!   stderrprintstdoutstripFileNotFoundErrorTimeoutExpiredstr)r.   r<   resultes       r0   _verify_augment_cli"AugmentService._verify_augment_cliU   s    	C**//#C!^^,Acggfb.A-BCCK  ^^;'#F   A%"9&-- IJJ,V]]-@-@-B,CDE  	YWXX(( 	8677 	C8QABB	Cs   B*B- -<D)D  Dc                 F    Xl         U R                  R                  S5        g)uk   设置日志回调函数

Args:
    callback: 日志回调函数，接受 (step_num, role, content) 参数
u   已设置日志回调函数N)r%   r,   debug)r.   callbacks     r0   set_log_callbackAugmentService.set_log_callbackq   s     %78r3   system_promptc                     U(       a$  U R                   (       a  U R                  SSS5        U R                  R                  S5        g)u   开始一个新的对话

注意：Augment 使用 guidelines 而不是 system_prompt，
所以这个方法主要是为了兼容性

Args:
    system_prompt: 系统提示（在 Augment 中会被忽略）
r   systemuJ   Augment 使用 .augment/rules/ 中的 guidelines，不使用 system_promptu+   Augment 对话开始（使用 guidelines）N)r%   r,   r-   )r.   rR   s     r0   start_conversation!AugmentService.start_conversationz   s:     T..a\^ 	FGr3   rolecontentc                 L    U R                   (       a  U R                  SX5        gg)u   添加消息到对话历史

注意：Augment 不维护对话历史，每次调用都是独立的
这个方法主要是为了兼容性

Args:
    role: 消息角色
    content: 消息内容
r   N)r%   )r.   rW   rX   s      r0   add_messageAugmentService.add_message   s"     a/ r3   languagevulnerabilitiesscene
difficultyextra_requirementscategory_id	form_datar(   returnc	           
          U(       Ga:  SSK Jn	Jn
  U
   U	R                  U0 5      nUR                  S0 5      nUR                  SS5      nU(       a  [        R
                  " U5        U R                  R                  S[        U5       S35        [        S[        U5       S[        UR                  5       5       3S	S
9  US:X  aZ  U(       aS  [        U5      nXS'   SU;  a  [        U5       Vs0 s H  oS_M     snUS'   U R                  R                  SU S35        OU R                  R                  S5        SSS5        U R                  XdXU5      nU(       d  [        SS	S
9  U R                  S-  S-  nUS-  nUR!                  5       (       a6  [#        UR%                  5       5      U l        [        SU R&                   3S	S
9  OfU R)                  U5        UR!                  5       (       a6  [#        UR%                  5       5      U l        [        SU R&                   3S	S
9  O
[        SS	S
9  U R+                  XX4XVU5      n[        S5        [        S5        [        S5        [        U5        [        S5        Xl        U R/                  UXhS9nU(       Ga  U R                  U-  S-  nUR!                  5       (       a  UR1                  5        Vs/ s H.  nUR3                  5       (       d  M  UUR4                  ;   d  M,  UPM0     nnU(       a  [7        US S9n[#        U5      nOUR1                  5        Vs/ s H  nUR3                  5       (       d  M  UPM     nnU(       a  [7        US  S9n[#        U5      nO5U R9                  U5      nO#U R9                  U5      nOU R9                  U5      nS!UUS".$ s  snf ! , (       d  f       GN= fs  snf s  snf ! [:         a*  n[#        U5      n[        S#U 35        S$USSS%.s SnA$ SnAff = f)&u  生成 CTF 题目（Augment 专用接口）

Args:
    language: 编程语言
    vulnerabilities: 漏洞名称列表（二级分类名称）
    scene: 场景名称（可能是字符串或字典）
    difficulty: 难度级别
    extra_requirements: 用户额外要求
    category_id: 方向ID
    form_data: 完整的表单数据（可选，用于传递所有表单字段）
    task_id: 任务ID（可选，用于创建独立工作目录避免多任务冲突）

Returns:
    包含生成结果的字典
r   generation_statusesgeneration_lockstage_namestotal_stagesu   已设置动态阶段配置: u
    个阶段u   📊 已加载 u    个阶段配置: Tflushstep_statuseswaitingu   已初始化 u    个阶段的状态u*   未找到阶段配置，使用默认阶段NuJ   ⚠️ 数据库中未找到 Prompt 配置，使用默认 guideline 文件.augmentrulesctf-generation-guide.mdu%   📜 使用已存在的规则文件: u"   📜 已设置默认规则文件: u@   ⚠️ 无法设置默认规则文件（目录可能不存在）=
============================================================u$   📝 传递给 Augment AI 的指令:<============================================================z=============================================================
)ra   r(   outputc                 6    U R                  5       R                  $ Nstatst_mtimeds    r0   <lambda>7AugmentService.generate_ctf_challenge.<locals>.<lambda>   s    affhFWFWr3   keyc                 6    U R                  5       R                  $ ru   rv   ry   s    r0   r{   r|     s    UVU[U[U]UfUfr3   success)statusresponse
output_diru   ❌ 生成CTF题目失败: error)r   messager   r   )app.routes.generator.utilsrf   rg   r   r   set_stage_namesr,   r-   lenrC   listvaluesrangewarning_setup_prompt_from_databaser   r    rH   resolve_current_rules_file_setup_guideline_for_difficulty_build_instructionr(   _call_augmentiterdiris_dirnamemax_find_latest_output_dirr!   )r.   r\   r]   r^   r_   r`   ra   rb   r(   rf   rg   task_statusrh   ri   idb_prompt_loaded	rules_dirdefault_rules_fileinstructionr   output_base_dirrz   matching_dirs
latest_dirr   challenge_dirslatest_challenge_dirrJ   	error_msgs                                r0   generate_ctf_challenge%AugmentService.generate_ctf_challenge   s   4l	[$"5"9"9'2"FK"-//-"DK#.??>1#EL"%55kB((+H[IYHZZd)efK0@/AASTXYdYkYkYmTnSopx|} (1,+.{+;L:F7.kAV[\hVi?jViQR9Vi?jO < KK,,}\NJ]-^_++,XY' %,  $??Yatyz#bjno !MMJ6@	%.1J%J"%,,../23E3M3M3O/PD,A$BZBZA[\dhi 88D)0022367I7Q7Q7S3T0 B4C[C[B\]eij `imn 11(U`r  BK  LK - 89&M+-  #L ))+;)`H "&--+"="H"))++0?0G0G0I %I0I1'(xxz &'6=6G &'0IM %I$%(<W%X
%(_
 6E5L5L5N)]5NRSRZRZR\!5N)])36~Kf3g0),-A)BJ)-)E)Ek)RJ!%!=!=k!JJ "99+F
 $$( Q @k! %_F%I *^&  
	AI/	{;< "$ "	 
	st   O CN</N7;AN<<FO O/OO2O 9OOAO 7N<<
OO 
P"PPPmessagestemperature
max_tokensstreamc                     Sn[        U5       H  nUS   S:X  d  M  US   n  O   U(       d  [        S5      eU R                  U5      nSUS.SS	./S
S
S
S.S.$ )u  执行聊天补全（兼容 OpenAI API 接口）

注意：这个方法主要用于兼容性，实际使用时建议使用 generate_ctf_challenge

Args:
    messages: 消息列表
    model: 模型名称（在 Augment 中被忽略）
    temperature: 温度参数（在 Augment 中被忽略）
    max_tokens: 最大 token 数（在 Augment 中被忽略）
    stream: 是否流式输出（在 Augment 中被忽略）

Returns:
    包含 AI 响应的字典
NrW   userrX   u   未找到用户消息	assistant)rW   rX   stop)r   finish_reasonr   )prompt_tokenscompletion_tokenstotal_tokens)choicesusage)reversed
ValueErrorr   )	r.   r   r   r   r   r   user_messagemsgr   s	            r0   chat_completionAugmentService.chat_completion  s    . H%C6{f$"9~ &
 455 %%l3 (' "(  "#%& !
 	
r3   c                 D    [         R                  " U R                  USS9  g)uJ   根据难度选择对应的guideline文件（委托给 GuidelineManager）T)r   N)r   setup_for_augmentr   )r.   r_   s     r0   r   .AugmentService._setup_guideline_for_difficultyR  s    **4==*dSr3   c                     SSK Jn  SSKJn  SSKJn  U" 5       (       d  [        SSS9  gUR                  R                  U5      n	U	(       d  [        S	U 3SS9  gS
SSSS.n
U
R                  US
5      nU	R                  5       nSnU(       GaQ  X;   GaK  X   nSSK
nSnSnSnUR                  " UU5      (       a  UU:  a  US-  n[        SU S3SS9  UR                  U	5      (       az  SSKJn  UR                  R                  U	5        U	R                  5       nU(       a7  X;   a2  X   nUR                  " UU5      (       d  [        SSS9  OA[        SSS9  O[        SSS9  O+[        SSS9  O UR                  " UU5      (       a  UU:  a  M  UU:  a&  UR                  " UU5      (       a  [        SU S3SS9  UR!                  UUUU5      n[        SU SU S3SS9  U(       d|  [        SU S U S!3SS9  UR                  U	5      (       a<  U	R                  5       nU(       a%  X;   a   UR!                  X   UUU5      n[        S"SS9  U(       d  [        SU S U S#3SS9  g[        S$[#        U5       S%3SS9  Xl        g! [&         a4  n[        S&[)        U5       3SS9  SSKnUR-                  5          SnAgSnAff = f)'u   从数据库加载 Prompt 并设置为 Augment 规则文件

Args:
    category_id: 方向ID
    difficulty: 难度级别
    language: 编程语言
    vulnerabilities: 漏洞列表
    scene: 场景

Returns:
    是否成功加载
r   )has_app_context)CategoryConfig)PromptCompilerServiceu>   ⚠️ 不在 Flask 应用上下文中，无法访问数据库Trj   Fu   ⚠️ 方向配置不存在: beginnereasymediumhard)u   入门u   简单u   中等u   困难Nu   阶段\s*\d+\s*末   r
   uC   ⚠️ 检测到旧的 Prompt 格式（包含'阶段X末'），第 u    次重新编译...)dbu@   ✅ 重新编译成功，已清理旧格式并保存到数据库u:   ⚠️ 重新编译后仍包含旧格式，继续重试...u)   ⚠️ 重新编译后仍未找到 Promptu   ⚠️ 重新编译失败u   ⚠️ 警告：重新编译 uJ    次后仍包含旧格式，可能 stage 配置中包含'阶段X末'内容u2   ✅ 已从数据库加载 Prompt 模板（方向: u
   , 难度: u   ）u#   ⚠️ 数据库中未找到方向 u    难度 u#    的 Prompt，尝试重新编译...u0   ✅ 重新编译成功，已加载 Prompt 模板u    的 Promptu&   ✅ 已加载 Prompt 模板，长度:     字符u&   ❌ 从数据库加载 Prompt 失败: )flaskr   app.models.database.modelsr   $app.services.prompt.compiler_servicer   rC   queryr   get_compiled_promptsresearchcompile_and_save_promptsr   sessionrefreshreplace_placeholdersr   _compiled_promptr!   rH   	traceback	print_exc)r.   ra   r_   r\   r]   r^   r   r   r   categorydifficulty_mapdifficulty_keycompiled_promptscompiled_prompt
old_promptr   old_format_patternmax_retriesretry_countr   rJ   r   s                         r0   r   *AugmentService._setup_prompt_from_databaseV  s6   (l	-AR"$$V^bc%++//<H6{mDDQ % " 	N ,//
JGN  (<<>"ON$F-=
 %:"  ii 2J??KR]D]1$K_`k_ll  A  IM  N -EEhOOA

**84 ,4+H+H+J(+0R)9)IJ#%99-?#L#L %(hqu v % %(bko p!$MVZ[! 9$G3 ii 2J??KR]D]6 +-"))<NPZ2[2[9+  GQ  R  Z^  _ #8"L"L#	# J;-Wablammpqy}~";K=Q[P\\  A  IM  N(AA(KK'/'D'D'F$'N,N*?*T*T,<$+!	+  PY]^&?}HU_T``kltxy  :3;O:PPWX`de %4! 	:3q6(C4P!		s0   (J  /J  D1J  CJ  "J   
J>
*J99J>c           	      r    U(       a  [         R                  " XgXX4U5      $ [         R                  " XX4U5      $ )u7   构建 Augment 指令（委托给 InstructionBuilder）)r   build_dynamic_instructionbuild_simple_instruction)r.   r\   r]   r^   r_   r`   ra   rb   s           r0   r   !AugmentService._build_instruction  sA     %??5Vh 
 &>>5>P r3   linec                 .    [         R                  " U5      $ )u>   检测输出行中的阶段信息（委托给 StageDetector）)r   detect_stage)r.   r   s     r0   _detect_stageAugmentService._detect_stage  s    ))$//r3   c                   ^ SSK nU R                  (       a  gUR                  " ST5      (       d  UR                  " ST5      (       a  gTR                  5       (       d  gUR                  " ST5      (       a  gUR                  " ST5      (       a  gUR                  " S	T5      (       a  gUR                  " S
T5      (       a  gUR                  " ST5      (       a  gST;   a  gST;   a  gST;   d  ST;   a  g[	        U4S jS 5       5      (       a  gST;   d  ST;   a  g/ SQn[	        U4S jU 5       5      (       a  gST;   a  [        TR                  5       5      S:  a  ggg)uv   判断是否应该打印这一行（非详细模式下）

Args:
    line: 输出行

Returns:
    是否应该打印
r   NTu   \[已输出 \d+ 行\]u   \[已处理 \d+ 行\]Fz\[90mz^\s{4,}[^\s]z2^\s+(command|cwd|wait|max_wait_seconds|path|type):z
^\s+\d+\s+u   (?:##\s*)?阶段\s*\d+[：:]u   🔧 Tool call:u   📋 Tool result:u   ✅ Command completedu   ✅ Successfullyc              3   ,   >#    U  H	  oT;   v   M     g 7fru    ).0markerr   s     r0   	<genexpr>4AugmentService._should_print_line.<locals>.<genexpr>,  s     o,n&~,n   )   ❌u   ⚠️Errorr   ERRORWarningWARNINGz
File savedz
Saved file)	BuildingzSuccessfully builtzSuccessfully taggedzCreating networkzCreating containerzStarting containerzContainer startedStoppingRemovingc              3   ,   >#    U  H	  oT;   v   M     g 7fru   r   )r   keywordr   s     r0   r   r   ?  s     >o7$or   u   🤖d   )r   r   r   rE   anyr   )r.   r   r   docker_keywordss    `  r0   _should_print_line!AugmentService._should_print_line  s[    	 << 99-t44		BZ\`8a8a zz|| 99Xt$$ 99_d++ 99JDQQ 99]D)) 994d;; $ $& #d*.@D.H o,nooo 4<4#7

 >o>>> T>4::< 3& r3   stageoutput_linesc                    SR                  U5      nSnU R                  (       aU   SSKJnJn  U   UR                  U R                  0 5      nUR                  S0 5      nU(       a  X;   a  UX   S.nSSS5        [        R                  " XUS9$ ! , (       d  f       N#= f! [         a(  n	U R                  R                  SU	 35         Sn	A	NSSn	A	ff = f)	u\   从输出中提取阶段关键信息（委托给 StageDetector，支持动态阶段配置）r7   Nr   re   rh   )idr   u   获取阶段配置失败: )stage_config)joinr(   r   rf   rg   r   r!   r,   rN   r   extract_stage_info)
r.   r   r  output_textr  rf   rg   r   rh   rJ   s
             r0   _extract_stage_info"AugmentService._extract_stage_infoL  s    ggl+ <<D[$"5"9"9$,,"KK"-//-"DK"u'; #($/$6( % //Q]^^ %_  D!!$>qc"BCCDs5   
B  AB2B  
BB  B   
C*CCc                    SSK Jn  SSKnU R                  U-  SU 3-  nU R                  U-  S-  nUR	                  SSS9  UR                  5       (       d  U R                  R                  SU 35        gUS-  nUR                  5       (       Ga-  UR                  5        Vs/ s H  oR                  5       (       d  M  UPM     n	nU	(       a  [        U	S	 S
9n
U
R                  nXk-  nUR                  5       (       a8  SSKnUR                  R                  5       R                  S5      nU SU 3nXk-  nUR                  " [!        U
5      [!        U5      5        U R                  R#                  SU 35         UR$                  " [!        U5      5        U R                  R#                  SU 35        [!        U5      $ US-  R                  5       nUS-  R                  5       nU(       d  U(       Gab  SSKnUR                  R                  5       R                  S5      nU S3nU(       a   US-  R)                  SS9nSSKnUR,                  " SUUR.                  5      nU(       aN  UR1                  S5      R3                  5       nUR4                  " SSU5      nUR4                  " SSU5      nU SU 3nXk-  nUR                  5       (       a8  Xk S[7        UR                  R                  5       R9                  5       5       3-  nUR                  " [!        U5      [!        U5      5        U R                  R#                  SU 35        [!        U5      $ U R                  R                  S5        U R;                  U5      $ s  snf ! [&         a)  nU R                  R                  SU 35         SnAGNSnAff = f! [&         a)  nU R                  R                  SU 35         SnAGN4SnAff = f)u   将临时工作目录移动到 output/ 目录

Args:
    category_id: 方向ID
    task_id: 任务ID
    
Returns:
    移动后的输出目录路径，如果失败则返回 None
r   r   Ntemp_rs   Tparentsexist_oku   临时目录不存在: c                 6    U R                  5       R                  $ ru   rv   ry   s    r0   r{   5AugmentService._move_temp_to_output.<locals>.<lambda>  s    IZIZr3   r}   z%Y%m%d_%H%M%S_u,   已将题目目录从临时目录移动到: u   已清理临时目录: u   清理临时目录失败: 
writeup.mddocker
_challengeutf-8encodingz)^#\s+([^#\n]+?)(?:\s*-\s*[Ww]riteup)?\s*$r
   z[^\w\s-]r7   z\s+u#   从 writeup 提取题目名失败: u   已将临时目录移动到: uE   临时目录中未找到题目文件，尝试查找最新输出目录)pathlibr	   shutilr   mkdirr    r,   r   r   r   r   r   datetimenowstrftimemoverH   r-   rmtreer!   	read_textr   r   	MULTILINEgrouprE   subint	timestampr   )r.   ra   r(   r	   r  temp_dirr   temp_output_dirrz   r   r   challenge_dir_name
target_dirr  r%  rJ   has_writeup
has_dockerwriteup_contentr   title_matchchallenge_names                         r0   _move_temp_to_output#AugmentService._move_temp_to_outputd  s    	!==;.5	1BB--+5@dT:  KK"9( DE #X-!!##)8)@)@)BQ)BAhhja)BNQ'*>?Z'[$%9%>%>" -A
$$&&# ( 1 1 5 5 7 @ @ QI,>+?q)L&!0!EJC 45s:G  #OPZ|!\]JMM#h-0KK$$'>xj%IJ :&  ,.668)113
*  ))--/88II$-;j!9 S'/,'>&I&ISZ&I&[O"$)),XZikmkwkw"xK")4):):1)=)C)C)E)+R)P)+^)L09{!N;K-L* )=J  "",1EQs8K\K\K`K`KbKlKlKnGoFp/qq
KKHs:7KK<ZLIJz?" 	ce++K88C R, ! JKK''*DQC(HIIJ: ! SKK''*MaS(QRRSs=   #N?N:9N -B	N< 
N9N44N9<
O/O**O/c                    SSK Jn  U R                  U-  S-  nUR                  5       (       aS  UR	                  5        Vs/ s H  oDR                  5       (       d  M  UPM     nnU(       a  [        US S9n[        U5      $ gs  snf )u   查找最新生成的输出目录（根据 category_id 查找对应的目录）

Args:
    category_id: 方向ID，默认为 'web'
r   r   rs   c                 6    U R                  5       R                  $ ru   rv   ry   s    r0   r{   8AugmentService._find_latest_output_dir.<locals>.<lambda>  s    8I8Ir3   r}   N)r  r	   r   r    r   r   r   rH   )r.   ra   r	   category_output_dirrz   subdirsr   s          r0   r   &AugmentService._find_latest_output_dir  st     	! #mmk9HD%%''"5"="="?N"?Q88:q"?GN .IJ
:& Os    BBsourcetargetc                 $   SSK nUR                  5       (       d  gUR                  5       (       d  UR                  SSS9  UR                  5        H  nX$R                  -  nUR                  5       (       aO  UR                  5       (       a  U R                  XE5        MN  UR                  " [        U5      [        U5      5        Mu  UR                  5       (       a8  UR                  5       (       a  UR                  5         OUR                  " U5        UR                  " [        U5      [        U5      5        M      UR                  5       (       a0  [        UR                  5       5      (       d  UR                  5         ggg! [         a     gf = f)u   递归合并目录内容（移动源目录内容到目标目录）

Args:
    source: 源目录路径
    target: 目标目录路径
r   NTr  )r  r    r  r   r   r   _merge_directoryr  rH   is_fileunlinkr  r   rmdirOSError)r.   r7  r8  r  itemtarget_items         r0   r:  AugmentService._merge_directory  s"    	}}}}LLL5NN$D 99,K{{}}%%''))$< KKD	3{+;< %%''"**,,#**, k2CIs;'78' %,	}}s6>>+;'<'< (= 		s   <AF 
FFr   c                     U R                   S-  SU R                   3-  n[        U5      S-  nUR                  5       (       d  [	        SU 3SS9  gUR                  SSS9  US	-  nUS	-  nUR                  5       (       a]  S
SKnUR                  5       (       a  U R                  XE5        O%UR                  " [        U5      [        U5      5        [	        SU 3SS9  S Hs  nX'-  nX7-  n	UR                  5       (       d  M"  S
SKnU	R                  5       (       a  U R                  X5        MN  UR                  " [        U5      [        U	5      5        Mu     g! [         a  n
[	        SU
 3SS9   Sn
A
gSn
A
ff = f)ud   将会话历史从全局缓存目录移动到题目目录

Args:
    output_dir: 题目输出目录
.augment_cacheuser_.augment_sessionu"   ⚠️  源缓存目录不存在: Trj   Nr  sessionsr   u!   ✅ 已将会话历史移动到: )binarieszcheckpoint-documentsztask-storageu"   ⚠️  移动会话历史失败: )r   r   r	   r    rC   r  r  r:  r  rH   r!   )r.   r   source_cachetarget_cachesource_sessionstarget_sessionsr  subdirsource_subdirtarget_subdirrJ   s              r0   _move_session_to_challenge_dir-AugmentService._move_session_to_challenge_dir  st   ,	H,,/??E$,,BXXL  
+.@@L&&((:<.IQUV td; +Z7O*Z7O%%''"))++))/K KKO 4c/6JK9,HPTU O , 5 , 5 ''))!$++----mK C$6M8JK O  	H6qc:$G	Hs&   AE B,E AE 
E9"E44E9r   c                    U R                   U-  nU(       a"  U R                  R                  SU SU 35        OU R                  R                  S5        UR	                  SSS9  US-  nSnUR                  5       (       a@  SSKnUS	[        UR                  " 5       5       3-  n UR                  U5        [        S
SS9  SSKn[        R                  " 5        S[        UR                  " 5       S-  5       3n	USU	 S3-  n
 [        U S5      (       aB  U R                  (       a1  U R                  nU SU 3nU
R                  USS9  [        SU
 3SS9  OU
R                  USS9  [        SU
 3SS9    [        R                   R#                  5       nU R$                   SUR'                  SS5       3US'   SnU R(                  (       a  SSKJnJn  U" U R(                  5      nU(       a  U" U5      nU(       ak  UUS'   [        SU R(                   S 3SS9  [        S!USS"  S#3SS9  U R0                  S$-  S%U R(                   3-  nUR	                  SSS9  [        S&U 3SS9  O5[        S'USS"  S#3SS9  O#[        S(U R(                   S)3SS9  O
[        S*SS9  SU;   a  [        S+[3        US   5       S,3SS9  O
[        S-SS9  S.S/[5        U
R7                  5       5      S0S1[5        UR7                  5       5      /nU R8                  (       aD  U R8                  S2:w  a4  UR;                  S3U R8                  /5        [        S4U R8                   3SS9  [        S5UR7                  5        3SS9  U(       a  UR;                  S6[5        U5      /5        SSKnUR?                  [@        5      nUR                  S7S8RC                  U5       35        UR                  S9U 35        UR                  S:U
R7                  5        35        SSK"nSS;K#J$n  U" S<5      nUR	                  SS=9  U(       a
  US>U S?3-  nOlSSK%nURD                  RM                  5       RO                  S@5       S[        R                  " 5        SURQ                  5       RR                  SSA  3nUS>U S?3-  nUR                  SBU SCU S,35        SSDK*J+nJ,n  U(       a0  U   UU;  a  0 UU'   [5        U5      UU   SE'   SUU   SF'   SSS5        OSSGK*J-n  [5        U5      USE'   SUSF'   UR                  " 5       nSSK.n [^        R`                  " U[^        Rb                  [^        Rd                  SU[5        U5      SSSH9n!/ n"Sn#SIn$SSJK3J4n%J5n&  U%" [5        U5      SK5       n' SLn(SIn$ U!Rl                  Ro                  5       n)U)(       d  U!Rq                  5       b  GOM7  U'Rs                  U)SS9  U"Ru                  U)5        U Rw                  U)5      (       a%  [        U)SSSM9  U Rl                  Ry                  5         SRC                  U"5      n*[z        R|                  " U*5      (       Ga  [        SNSS9  U'R                  SO5        [z        R                  " 5       n+U+S:  a  [        U+5       Hj  n,U,U$:  d  M  SRC                  U"5      n-[        U SP5      (       a  U R                  U,U"5      OSn.[z        R                  " U,5      n/U'R                  U,U/SQ5        Ml     U$S:  a_  SRC                  U"5      n-[        U SP5      (       a  U R                  U$U"5      OSn.[z        R                  " U$5      n/U'R                  U$U/SQ5        Sn(GOqU R                  U)5      n0U0b  [        SRU0 SSU$ 3SS9  U0b  U0U$:w  a  [        STU$ SUU0 3SS9  U(       aT  SSDK*J+nJ,n  U   UR'                  U0 5      n1U1R'                  SV0 5      n2U2(       a  [z        R                  " U25        SSS5        SRC                  U"5      n-[z        R                  " U$U0U-U R                  U R                  SW9n$[z        R                  " U$5      n3U'R                  U$U3SX5        U#SY-  n#U R                  (       a+  U#SZ-  S:X  a"  S[U# S\3n4[        U4SS9  U'R                  U45        O/U R                  (       d  U#SZ-  S:X  a  U'R                  S[U# S\35        GMH   U!R                  S]S^9  U((       d<  SRC                  U"5      n-[z        R                  " U$U-U R                  U R                  S`9  UR                  " 5       U-
  n5U'R                  SaU5Sb Sc35        U R                  R                  SdU5Sb Sc35         SSS5        SRC                  U"5      n6U!R                  S:w  Ga  SgU!R                   3n7U R                  R                  U75        SLn8Sn9 U" U5      R                  n:ShU:;   a+  U:R                  Sh5      n;[3        U:5      U;SY-   :  a  U:U;SY-      n9U" GH  n)SiU);   d  M  [z        R                  " U)[5        U R                   5      5      n<U<(       d  M?  [        R                  R                  U<5      (       d  Me  [        R                  R                  [        R                  RC                  U<Sj5      5      n=[        R                  R                  [        R                  RC                  U<Sk5      5      n>[        R                  R                  [        R                  RC                  U<Sl5      5      n?U=(       d
  U?(       d  GM-  Sn8[        R                  R                  U<5      n@[        SmU@ 35        [        SnU=(       a  SoOSp 35        [        SqU>(       a  SoOSp 35        [        SrU?(       a  SoOSp 35          O   U8(       d/  U R                  (       a  U R                  SSsU75        [        U75      eStU!R                   Su3nA[        SvUA 35        SU lW        UAU lX        U R                  (       a  U R                  SSwU7 Sx35        U R                  (       a  U R                  SSyU65        [        Sz[3        U65       S{35        U6 S|[        5       ;   a2  U
R                  5       (       a  U
R                  5         [        S}U
 3SS9   S[        5       ;   a?  U(       a7  UR                  5       (       a!  US-  nBUR                  UB5        [        SSS9  $ $ $ $ ! [         a  n[        SU S3SS9   SnAGNgSnAff = f! [         a)  n[        SU S3SS9  U
R                  USS9   SnAGNSnAff = f! , (       d  f       GNf= f! , (       d  f       GN= f! [^        R                   a    U!R                  5         [        S_5      ef = f! [         aJ  nU'R                  Se[5        U5       3U5        U R                  R                  Se[5        U5       3SSf9  e SnAff = f! , (       d  f       GN= f!    GN= f! [         a  n[        S~U 3SS9   SnAGNSnAff = f! [         a  n[        SU 3SS9   SnA$ SnAff = f! [^        R                   a@    S_n7[        SU7 35        U R                  (       a  U R                  SSsU75        [        U75      e[         aF  nS[5        U5       3n7[        SU7 35        U R                  (       a  U R                  SSsU75        e SnAff = f!  S|[        5       ;   a2  U
R                  5       (       a  U
R                  5         [        S}U
 3SS9  O$! [         a  n[        S~U 3SS9   SnAOSnAff = f S[        5       ;   a?  U(       a7  UR                  5       (       a!  US-  nBUR                  UB5        [        SSS9  f f f f ! [         a  n[        SU 3SS9   SnAf SnAff = f= f)u   调用 Augment CLI 执行指令

Args:
    instruction: 用户指令
    category_id: 方向ID，用于设置工作目录
    task_id: 任务ID（可选，用于创建独立工作目录避免多任务冲突）

Returns:
    Augment 的响应文本
u4   使用共享工作目录（与 API 模式一致）: u   ，task_id=uF   未提供 task_id，使用共享工作目录（与 API 模式一致）Tr  z	CLAUDE.mdNr   zCLAUDE.md.backup_uN   📌 已临时重命名工作目录下的 CLAUDE.md，避免规则文件冲突rj   u#   ⚠️ 重命名 CLAUDE.md 失败: u$   ，可能会造成规则文件冲突r  i  z.augment_rules_.mdr   z

---

r  r  u9   📜 已将 Prompt 和用户指令合并到临时文件: u=   ⚠️ 未找到编译后的 Prompt，仅使用用户指令: u!   ⚠️ 创建合并文件失败: u!   ，回退到仅使用指令文件r5   r6   r7   get_user_augment_tokenconvert_token_to_augment_formatAUGMENT_SESSION_AUTH   ✅ 已设置用户     的Augment Tokenu   🔑 Token (前50字符): 2   z...rC  rD  u   📂 用户缓存目录: u'   ❌ Token 转换失败，原始 Token: u   ⚠️  警告: 用户 u,    未设置Token，将使用系统默认Tokenu>   ⚠️  警告: 未指定用户ID，将使用系统默认Tokenu9   ✅ 环境变量 AUGMENT_SESSION_AUTH 已设置 (长度: )u0   ❌ 环境变量 AUGMENT_SESSION_AUTH 未设置!r8   -if-p--workspace-rootr   z--modelu   🤖 使用模型: u   📂 工作目录: --augment-cache-diru   执行 Augment CLI:  u   工作目录: u   合并的规则文件: r   logsr  augment_.txt%Y%m%d%H%M%S   u   日志文件: z (task_id: re   log_filelog_position)generation_statusrD   rB   r;   r<   cwdbufsizeuniversal_newlines)UnifiedLogWriterLogLevelAugmentFendrk   u9   ✅ 检测到生成完成标记 [CTF_GENERATION_COMPLETE]u3   检测到生成完成标记，所有阶段已完成r  u   完成u   🔍 检测到阶段标记: u   , 当前阶段: u   🔄 阶段切换: z -> rh   )current_stage	new_stager  extract_info_funcr,   u   开始r
   r   u   [已处理 u    行]X  r=   .   Augment CLI 执行超时（超过 10 分钟）)rs  r  ru  r,   u   Augment 执行完成，耗时: .2f    秒u   Augment 执行时间: u   Augment 执行异常: )exc_info&   Augment CLI 执行失败，返回码: r   zoutput/r  zexp.pyr  u<   ⚠️  虽然AI超时，但检测到题目文件已生成: z   - writeup.md: u   ✅r   z   - exp.py: z   - docker/: r   u   AI执行超时（返回码: u$   ），但题目文件已完整生成u   ⚠️  r   u   （但文件已生成）r   u)   ✅ Augment 执行完成，输出长度: r   temp_rules_fileu!   ✅ 已清理临时规则文件: u!   ⚠️ 清理临时文件失败: claude_md_backupu   ✅ 已恢复 CLAUDE.md 文件u&   ⚠️ 恢复 CLAUDE.md 文件失败: u   ❌    Augment CLI 执行异常: )[r   r,   r-   r   r  r    timer$  renamerC   r!   r   getpidhasattrr   
write_textr   r>   r   r   r   &app.services.ai.helpers.augment_helperrT  rU  r   r   rH   r   r   extendr)   r*   r+   r  r  r  r	   uuidr  r  uuid4hexr   rf   rg   rh  sysr?   PopenPIPESTDOUT"app.services.ai.core.log_formatterrn  ro  rD   readlinepoll	write_rawappendr   rk   r   detect_completionwrite_successget_total_stagesr   r  get_stage_namewrite_stager   r   handle_stage_transitionr   
write_infowaitrG   killfinalize_stagewrite_errorr   rA   partsindexdetect_output_dirpathbasenamer%   r&   r'   localsr<  )Cr.   r   ra   r(   workspace_dirclaude_md_in_workspacer~  r  rJ   unique_suffixr}  rules_contentcombined_contentr<   user_cache_dirrT  rU  	token_strconverted_tokencmdr)   r,   r  r	   log_dirrf  r  	unique_idrf   rg   rh  
start_timer  processr  
line_countrs  rn  ro  
log_writergeneration_completer   output_text_so_farri   	stage_numr  
stage_info
stage_namestage_detectedr   rh   	stage_msgprogress_msgelapsed_timers   r   output_dir_foundcategory_id_from_workspaceworkspace_parts
ge10_indexdetected_dirr*  has_expr+  dir_namewarning_msgoriginal_namesC                                                                      r0   r   AugmentService._call_augment2  s    3KKSTaSbbmnumvwxKK hiD48 "/!<!((**,1B3tyy{CSBT/UUq&--.>?fost 	99;-qTYY[4-?)@(AB'OM?#*NN	Ft/00T5J5J $ 5 5&3_K}#M **+;g*NQRaQbckop  **;*IUVeUfgostT	P**//#C!^^,Acggfb.A-BCCK "N||z24<<@	&Ei&PO&6E23 4T\\NBST\`a :?3B;O:PPST\`a *.):):=M)MRWX\XdXdWePf)f&,,TD,I 9.9IJRVW G	RUSUGWWZ[cgh3DLL>Amnvz{V^bc &,QRUVYZpVqRrQsstu  ~B  CHQUV
 s?2245"C(=(=(?$@	C zzdjjI5

Itzz23+DJJ<8E'(=(=(?'@AN 

13~3FGH&&x0FKK.sxx}o>?KK.89KK1/2I2I2K1LMN $ 6lGMM4M( "xy%== '00446??OPPQRTR[R[R]Q^^_`d`j`j`l`p`pqsrs`t_uv	"x	{$%??KK.
+gYaHI X$&9979+G4?B8}'0<CD'0@	 %_ I03H!*-45!.1 J  &&!!((&#'	G LJM V!#h-;zs*/'$&M&~~668#&||~9 %$ #,,T,>$++D1  22488!$Bd;JJ,,. .0WW\-B*(::;MNN!$]fjk&445jk ,9+I+I+KL+a/16|1DI'0='@68ggl6Kjqrv  yN  kO  kOT5M5MiYe5f  UY
5B5Q5QR[5\
(2(>(>y*V^(_ 2E $1A#524'',2GKjqrv  yN  kO  kO1I1I-Ye1f  UYJ1>1M1Mm1\J$.$:$:=*V^$_ 37/! *.););D)A)5!$@@PP`an`o"px|})5.M:Y!$7d>JZ"[cgh  ' k%42E2I2I'SU2VK2=//-QS2TK'2(5(E(Ek(R	 &5 +-'',*?K,9,Q,Q.;*8,7262J2J'+{{-M )6(D(D](SI&22=)XV #a
<<J,<,A-8E+JL!,d;&11,?!%*s2Ba2G&11K
|52QRi nZS1 /&(ggl&;%44*7(3.2.F.F#';;	 $(99;#;L,,/N|\_N``d-efKK$$'=l3=Ot%TU_ <n WW\*F !!Q&DWEWEWDXY	!!), $) -1*&*=&9&?&?O0%4%:%:6%B
/*q.@9HVW9X6
 )D D('4'F'FtSQUQ^Q^M_'`'<BGGNN<,H,H*,''..lT`9a*bK&(ggnnRWW\\,PX5Y&ZG)+\S[8\)]J*jj37 0+-77+;+;L+I %(demdn&o p %(9;%TY9Z&[ \ %weE5R&S T %
uPU6V&W X %# )& ((())!Wi@#I.. %AASAS@TTx"yKH[M23 .2D*+6D((())!Y9+E]8^_   !!![&9=c&k]'RS,K$0_5K5K5M5M#**,=o=NOW[\
P%16FK[KbKbKdKd$1K$?M$++M::4H Le6F1S  q;A3>bckoppq*  	F5aS8YZbfg&&{W&E	Ft %_B &5_B &44 Z'(XYYZ$ ! **-CCF8+LaPKK%%(>s1vh&GRV%W	a <;RN  K9!=TJJK  P>qcB$OPC (( 	'HID$%  !!!Wi8I&& 	4SVH=ID$%  !!!Wi8	K$0_5K5K5M5M#**,=o=NOW[\ K9!=TJKP%16FK[KbKbKdKd$1K$?M$++M::4H Le6F1  P>qcB$OPs  %t	 At/ t/ 5My6 %u%,By6 xDv<Dv</Au71C!v<v	"Bv<0Ay6 	Ax% 
y6 /y6 "y6 3Cy6 ;D>y6 :A x-;A
y	
t,t''t,/
u"9uu"%
u4/y6 7
v	v<	0v99v<<
xAxxx
x"y6 %x*'y6 -
y7y

y
y3y..y36A|A||| 5A }5
}?(}:55:}??5A
5
2-(5-225challenge_idc                     U(       a$  [         R                  R                  U5      (       d  [        SU 35      e[	        U5      nUS-  nUR                  SS9  [        SU 35        [        U5      [        U5      S.$ )uN  为题目创建独立的工作空间（直接使用题目的output_dir）

Args:
    challenge_id: 题目ID
    output_dir: 原始输出目录路径(ge10/{category_id}/output/xxx)

Returns:
    包含工作空间信息的字典:
    {
        'workspace_dir': 工作空间目录路径,
        'session_dir': 会话目录路径
    }
u   题目输出目录不存在: rE  Tra  u*   ✅ 使用题目目录作为工作空间: )r  session_dir)r   r  r    r   r	   r  rC   rH   )r.   r  r   r  r  s        r0   create_isolated_workspace(AugmentService.create_isolated_workspace  s     
!;!;<ZLIJJ Z( $&884(
 	:=/JK !/{+
 	
r3   r  c                    US-  n UR                  U R                  5      n[        UR                  5      nSnU(       a"  S H  nXr:w  d  M
  USU S3-  nUSU S3-  nM     US-  nUR                  U5        U R                  R                  S	U 35        US
-  S-  nUR                  SSS9  U R                  S
-  S-  S-  n	US-  n
U	R                  5       (       aI  U
R                  5       (       d4  SSK
nUR                  " X5        U R                  R                  SU
 35        US-  nUR                  5       (       d  UR                  S5        [        S5        g! [         a    Sn GN5f = f)u   在工作空间中创建安全配置文件和规则文件

Args:
    workspace_dir: 工作空间目录
    category_id: 方向ID，用于限制访问范围
z.augmentignore   u~  # 安全限制:禁止访问工作空间外的文件
# 严格限制：只能访问当前工作目录及其子目录

# 禁止访问父目录（多层防护），但允许访问共享资源（data/）
../*
../../*
../../../*
../../../../*
../../../../../*

# 允许访问父目录的共享资源（同一 category 下的 data/ 目录）
!../data/

# 禁止访问其他方向的目录
)webpwnreversecryptomiscz../z/*
z../../u  # 禁止访问系统敏感目录
/etc/*
/root/*
/home/*
~/*
/usr/*
/var/*
/bin/*
/sbin/*
/opt/*

# 禁止访问项目根目录外的任何内容
../../../*
../../../../*

# 允许访问当前目录和子目录（output/、data/ 等）
!output/
!data/
!prompts/
u$   已创建/更新安全配置文件: rn   ro   Tr  rp   r   Nu+   已复制 CTF 生成规则到工作空间: zREADME_SECURITY.mduy  # 工作空间安全说明

⚠️ **重要提示**

这是一个CTF题目工作空间。请注意:

1. **只能修改当前目录内的文件**
2. **禁止访问父目录或其他题目的文件**
3. **禁止执行危险的系统命令**
4. **所有修改应该围绕完善当前题目进行**

## 允许的操作

- 修改源代码文件
- 修改Docker配置
- 修改writeup.md
- 添加新的测试文件
- 修复构建错误
- 添加提示文件

## 禁止的操作

- 访问 `../` 父目录
- 删除整个工作空间
- 修改其他题目的文件
- 访问系统敏感目录

请遵守这些规则,专注于完善当前题目。
u%   ✅ 已创建工作空间安全配置)relative_tor   r   r  r   r  r,   r-   r  r    r  copy2rC   )r.   r  ra   augmentignoreworkspace_relativedepthignore_rules	other_dirr   source_ruletarget_ruler  readmes                r0   !_create_workspace_security_config0AugmentService._create_workspace_security_config  s    &(88	!.!:!:4==!I*001E  H	+ c)D$99L fYKt$<<L I
 	  	, 	  .?OP "J.8	t4 mmj07:=VV";;(:(:(<(<LL2KKJ;-XY !55}}  < 	57E  	E	s   0E E-,E-c                     / SQnU H8  u  p4[         R                  " X1[         R                  5      (       d  M1  SSU 34s  $    g)u   验证用户指令的安全性

Args:
    instruction: 用户输入的指令

Returns:
    (is_valid, error_message): 是否有效和错误信息
))z\.\./+u   禁止访问父目录)z/etc/u   禁止访问系统配置目录)z/root/u   禁止访问root目录)z!/home/(?!.*workspaces/challenge_)u   禁止访问其他用户目录)zrm\s+-rf\s+/u!   禁止执行危险的删除命令)zworkspaces/challenge_\d+(?!/)u'   禁止访问其他题目的工作空间)zsudo\s+u   禁止使用sudo命令)zchmod\s+777u   禁止修改文件权限为777Fu   安全检查失败: )TN)r   r   
IGNORECASE)r.   r   FORBIDDEN_PATTERNSpatternr   s        r0   validate_user_instruction(AugmentService.validate_user_instruction_  sF    
 #5Gyyr}}== 4YK@@@ #5 r3   user_instruction
session_idc                    U R                  U5      u  pVU(       d  [        U5      e[        U5      nUR                  5       (       d  U R                  U-  nUR                  5       (       d  [        SU 35      eU R                  S-  n UR                  5       n	UR                  5       n
U	R                  U
5        [        SS 35        [        SU 35        [        SU 35        [        S	U 35        U(       a  [        S
U 35        [        S S35        U R                  UUUS9nSUS   US   US.$ ! [        [        4 a    [        SU S35      ef = f)u-  继续之前的对话来完善题目

Args:
    challenge_id: 题目ID
    workspace_dir: 工作空间目录
    user_instruction: 用户新的指令
    session_id: 会话ID（可选，如果提供则恢复特定会话）

Returns:
    执行结果字典，包含 response, session_id, workspace_dir
   工作空间不存在: r   (   工作空间路径不合法，必须在 
    目录下
rr   u   💬 继续对话 - 题目 #   📂 工作空间:    📝 用户指令:    🔗 会话ID: r   r  r  r   r   r  )r   r   r  r  )r  r   r	   is_absoluter   r    r   r  RuntimeErrorrC   _call_augment_continue)r.   r  r  r  r  is_validr   workspace_pathr   workspace_resolvedge10_resolvedrI   s               r0   continue_conversation$AugmentService.continue_conversation|  s   & #<<=MNY'' m, ))++!..?N$$&&6}oFGG $$v-	^!/!7!7!9$,,.M**=9 	6(m,\N;<#M?34#$4#567OJ<01m ,,('! - 
  z* .*	
 	
% L) 	^GzQ[\]]	^s   1D2 2 Ec              #     #    U R                  U5      u  pVU(       d  [        U5      e[        U5      nUR                  5       (       d  U R                  U-  nUR                  5       (       d  [        SU 35      e UR                  5       R                  U R                  R                  5       5        [        SS 35        [        SU 35        [        SU 35        [        SU 35        U(       a  [        S	U 35        [        S S35        U R                  UUUS
9 H  nUv   M	     g! [         a    [        SU R                   S35      ef = f7f)u   继续对话 - 流式输出版本

Args:
    challenge_id: 题目ID
    workspace_dir: 工作空间目录
    user_instruction: 用户新的指令
    session_id: 会话ID（可选）

Yields:
    输出的文本块
r  r  r  r  rr   u(   💬 继续对话（流式） - 题目 #r  r  r  r  N)
r  r   r	   r  r   r    r   r  rC   _call_augment_continue_stream)	r.   r  r  r  r  r  r   r  chunks	            r0   continue_conversation_stream+AugmentService.continue_conversation_stream  s`    & #<<=MNY'' m,))++!..?N$$&&6~6FGHH	g""$001B1B1J1J1LM 	6(m8GH#M?34#$4#567OJ<01m 77('! 8 
E
 K
  	gGHYHYGZZdeff	gs   A8E;7D* 2A8E*$EEr  c                     SSK nUR                  " S5      nUR                  SU5      nUR                  " SSU5      nUR                  " SSU5      nUR                  " SSU5      nUR                  " SSU5      nU$ )	u?   对流式输出的文本块进行基本清理，保留换行符r   N%\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])r7   ,   📂\s*Resumed session from[^🤖\n]*🤖\s*#   📂\s*Resumed session from[^\n]*\nResumed session from[^\n]*\n   ^[🤖🧑👤]\s*)r   compiler#  )r.   r  r   ansi_escapecleaneds        r0   _clean_stream_chunk"AugmentService._clean_stream_chunk  s{     jj!IJ//"e, &&H"gV&&?WM&&8"gF &&.G<r3   rs   c                 *   SSK nUR                  " S5      nUR                  SU5      nUR                  " SSU5      nUR                  " SSU5      nUR                  " SSU5      nUR                  " SSXBR                  S	9nUR                  " S
SU5      nUR                  " SSU5      nUR                  " SSU5      nUR	                  S5      nU Vs/ s H  ofR                  5       PM     nnSR                  U5      nUR                  5       nU$ s  snf )u   清理Augment CLI的输出，移除ANSI颜色代码和不必要的调试信息

Args:
    output: 原始输出

Returns:
    清理后的输出
r   Nr  r7   r  r   r  u   ^[🤖🧑👤]\s*\n)flagsu   \n[🤖🧑👤]\s*\nr  r  z\n{3,}z

)r   r  r#  r!  splitrstripr  rE   )r.   rs   r   r  r  linesr   cleaned_liness           r0   _clean_augment_output$AugmentService._clean_augment_output  s    	 jj!IJ//"f- &&H"gV &&?WM&&8"gF &&0"g\\R&&14A &&.G< &&FG4 d#3895459))M* --/ :s   Dc                 v    SSK nUR                  " SXR                  5      nU(       a  UR                  S5      $ g)u   从Augment CLI输出中提取会话ID

Args:
    output: Augment CLI的输出

Returns:
    会话ID，如果未找到则返回None
r   Nzsession[:\s]+([a-f0-9-]{36})r
   )r   r   r  r"  )r.   rs   r   matchs       r0   _extract_session_id_from_output.AugmentService._extract_session_id_from_output0  s2     	 		96==Q;;q>!r3   session_cache_dirr   assistant_messagec                    SSK nSSKJnJn  US-  U S3-  nUR                  5       (       d.  SSKn	U	R                  [        5      n
U
R                  SU 35        g [        USSS	9 nUR                  " U5      nSSS5        S
UUSUR                  5       R                  5        3SSSU0S./S.0nWS   R                  U5        UR                  UR                  5      R                  5       R                  SS5      US'   [        USSS	9 nUR                   " XSSS9  SSS5        [#        S[%        US   5       S3SS9  g! , (       d  f       N= f! , (       d  f       N:= f! [&         a  n[#        SU 3SS9   SnAgSnAff = f)u+  手动保存对话到会话文件

因为使用 -p (print mode) 时，Augment CLI 不会自动保存会话历史，
所以我们需要手动更新会话文件。

Args:
    session_cache_dir: 会话缓存目录
    session_id: 会话ID
    user_message: 用户消息
    assistant_message: AI回复
r   N)r  timezonerF  z.jsonu&   会话文件不存在，无法保存: rr  r  exchangezmanual-r
   rX   )r  type	text_node)request_messageresponse_text
request_idrequest_nodeschatHistoryz+00:00ZmodifiedwFr  )ensure_asciiindentu)   ✅ 已保存对话到会话文件（共 u    条）Trj   u   ⚠️  保存会话失败: )jsonr  r  r    r)   r*   r+   r   openloadr  r%  r  utc	isoformatreplacedumprC   r   r!   )r.   r  r  r   r  r&  r  r  session_filer)   r,   fsession_datanew_exchangerJ   s                  r0   _save_conversation_to_session,AugmentService._save_conversation_to_sessionA  s   $ 	/(:5:,e8LL""$$&&x0FNNCL>RS#	BlC':a#yy| ;
 '3%6$+HLLN,D,D,F+G"H #$$% )<*&	L" '..|< (0||HLL'A'K'K'M'U'UV^`c'dL$ lC':a		,aH ; =c,}B]>^=__fgost= ;:6 ;:
  	B04DA	BsI   E$ 'E:BE$ E"E$ 
EE$ 
E!E$ $
F.F  Fc                 
   [         R                  " SSSSS9 nUR                  U5        UR                  nSSS5         [	        U5      nUR                  5       (       d  U R                  U-  n[        UR                  5       5      n[        R                  R                  5       nU R                   SUR                  SS	5       3US'   U R                  (       aE  S
SKJn	Jn
  U	" U R                  5      nU(       a$  U
" U5      nXS'   [%        SU R                   S3SS9  US-  nUR'                  SSS9  [%        SU 3SS9  U(       a  SSUSWSSU/n[%        SU 3SS9  OSSSWSSU/n[%        SSS9  UR)                  S[        U5      /5        [%        SSR+                  U5       3SS9  [%        SU 3SS9  [%        S SS9  S
SKn[	        S!5      nUR'                  SS"9  U R.                  (       a  US#U R.                   S$3-  nOlS
SKnUR,                  R3                  5       R5                  S%5       S&[        R6                  " 5        S&UR9                  5       R:                  SS'  3nUS#U S$3-  n[<        R<                  " 5       n[>        R@                  " U[>        RB                  [>        RD                  SUUS
SS(9n/ n[G        USSS)9 nURH                   HV  nURK                  U5        U RM                  U5      (       a  [%        US	SS*9  UR                  U5        URO                  5         MX     URQ                  S+S,9  SSS5        [<        R<                  " 5       U-
  n[%        S-5        [%        S.US/ S035        [%        S 5        S	R+                  U5      nURR                  S
:w  a  [U        S1URR                   35      eU RW                  U5      nUnU(       d  U RY                  U5      nU(       d  U(       a  US2-  nUR[                  5       (       al  S
SK.nUR]                  [        US3-  5      5      nU(       aD  [_        U[        R`                  Rb                  S49n [	        U 5      Rd                  n[%        S5U 3SS9  U(       a  U(       a  U Rg                  UUUUS69  UUS7. [        Rh                  " U5        $ ! , (       d  f       GN= f! , (       d  f       GN= f!    $ = f! [>        Rj                   a    WRm                  5         [U        S85      e[T         a  n![U        S9[        U!5       35      eSn!A!ff = f!  [        Rh                  " W5        f !    f = f= f):u   调用 Augment CLI 继续对话

Args:
    instruction: 用户指令
    workspace_dir: 工作空间目录
    session_id: 会话ID（可选，如果提供则恢复特定会话）

Returns:
    包含响应文本和会话ID的字典
r#  rR  Fr  modesuffixdeleter  Nr5   r6   r7   r   rS  rV  rW  rX  Trj   rE  r  u   📂 会话目录: r8   --resumer[  r\  r]  u   📌 恢复会话: 
--continueu   📌 继续最近的会话r^  u(   🚀 执行 Augment CLI (继续对话): r_  r  rr   r`  ra  augment_continue_rc  rd  r  re  ri  r  rq  rv  rw  rq   u   ⏱️  执行时间: ry  rz  r|  rF  *.jsonr}   u   📌 检测到会话ID: r  r  r   r  )r   r  rx  r  )7tempfileNamedTemporaryFilewriter   r	   r  r   rH   r   r   r   r>   r   r   r   r  rT  rU  rC   r  r  r  r  r(   r  r  r  r  r  r  r  r?   r  r  r  r'  rD   r  r   rk   r  rA   r!   r  r  r    globr   r  getmtimestemr1  r<  rG   r  )"r.   r   r  r  r.  instruction_filer  workspace_absr<   rT  rU  r  r  r  r  r  r  rf  r  r  r  r  r  log_fr   r  rs   cleaned_outputextracted_session_idsessions_dirr@  session_fileslatest_sessionrJ   s"                                     r0   r  %AugmentService._call_augment_continue  s7   " ((	

 GGK  vv
\	!-0N!--//!%!2!2^!C 6 6 89M **//#C!^^,Acggfb.A-BCCK ||z24<<@	&Ei&PO2A./0>OPX\] !/1C C##D4#@'(9':;4H
  
+& +J<8E  +& 2$? JJ-s3D/EFG<SXXc]OLTXY'7tD($' 6lGMM4M( ||"'8d%KK '00446??OPPQRTR[R[R]Q^^_`d`j`j`l`p`pqsrs`t_uv	"'84%HH J &&!!((!#'	G Lhg6%#NND ''- ..t44d$7 KK%KKM + S) 7  99;3L/"*<*<DAB(OWW\*F!!Q&"HI[I[H\ ]^^ "77?N $. ''+'K'KF'S$ (,=0:=&&(($(IIc,2I.J$KM$),]@P@P)Q/3N/C/H/H, 89M8NOW[\ $(922&73!,&4	 3  +2		*+G
 
@ 76H (( 	NLLNLMM 	C8QABB	C		*+sm   R:JS% 
A6S E"S% #S:
S	
SS% S"%8T9T44T99T< <U>UUUUc              #     #    [         R                  " SSSSS9 nUR                  U5        UR                  nSSS5         [	        U5      nUR                  5       (       d  U R                  U-  n[        UR                  5       5      n[        R                  R                  5       nU R                   SUR                  SS	5       3US'   U R                  (       a-  S
SKJn	Jn
  U	" U R                  5      nU(       a  U
" U5      nXS'   US-  nUR%                  SSS9  U(       a  SSUSWSSU/nO	SSSWSSU/nUR'                  S[        U5      /5        [(        R*                  " U[(        R,                  [(        R.                  SUUSSS9n/ nUR0                   H)  nUR3                  U5        U R5                  U5      nUv   M+     UR7                  SS9  UR8                  S
:w  a  [;        SUR8                   35      eS	R=                  U5      nU R?                  U5      nUnU(       d  U RA                  U5      nU(       d  U(       ay  US-  nURC                  5       (       a_  S
SK"nURE                  [        US-  5      5      nU(       a7  [G        U[        RH                  RJ                  S9n[	        U5      RL                  nU(       a  U(       a  U RO                  UUUUS9   [        RT                  " U5        g! , (       d  f       GN= f! [(        RP                   a    WRS                  5         [;        S 5      e[:         a  n[;        S![        U5       35      eSnAff = f!    g= f!  [        RT                  " W5        f !    f = f= f7f)"u   调用 Augment CLI 继续对话 - 流式输出版本

Args:
    instruction: 用户指令
    workspace_dir: 工作空间目录
    session_id: 会话ID（可选）

Yields:
    输出的文本块
r#  rR  Fr  r4  Nr5   r6   r7   r   rS  rV  rE  Tr  r8   r8  r[  r\  r]  r9  r^  r
   ri  rv  rw  r|  rF  r;  r}   r<  rx  r  )+r=  r>  r?  r   r	   r  r   rH   r   r   r   r>   r   r   r   r  rT  rU  r  r  r?   r  r  r  rD   r  r  r  rA   r!   r  r  r  r    r@  r   r  rA  rB  r1  rG   r  r<  )r.   r   r  r  r.  rC  r  rD  r<   rT  rU  r  r  r  r  r  full_outputr   cleaned_chunkrs   rF  rG  rH  r@  rI  rJ  rJ   s                              r0   r  ,AugmentService._call_augment_continue_stream;  sa    " ((	

 GGK  vv
k	!-0N!--//!%!2!2^!C 6 6 89M **//#C!^^,Acggfb.A-BCCK ||z24<<@	&Ei&PO2A./ !/1C C##D4#@ 
+&  +& JJ-s3D/EFG !&&!!((!#'	G K""4( $ 8 8 >##	 ' LLL%!!Q&"HI[I[H\ ]^^ WW[)F!77?N $. ''+'K'KF'S$',=0:=&&(($(IIc,2I.J$KM$),]@P@P)Q/3N/C/H/H, $(922&73!,&4	 3 		*+e
 
T (( 	NLLNLMM 	C8QABB	C		*+sv   NK9NJ L "M" 8N9
LN8MMMM) "M&$N)N	+NN	NN		N)r   r   r$   r   r%   r,   r   r   r   r#   r"   r(   r&   r'   r   r   )NNFNru   )r7   r  NN)r   gffffff?NF)r7   r  N)r  )r  N)/r+   
__module____qualname____firstlineno____doc__r   rH   r$  boolr1   rK   rP   rU   rZ   r   r   r   r   r   floatr   r   r   r   r   r   r   r  r/  r   r	   r:  rO  r   r  r  tupler  r  r  r  r  r  r1  r  r  __static_attributes__r   r3   r0   r   r      s   %9:(3- 9:# 9:`d 9:u}  B  vC 9:vC89H H0 0c 0( #% .2!%FF cF S$sCx.()	F
 F  F F DcN+F #F 
c3hFV  $(1
tCH~&1
 1
 	1

 SM1
 1
 
c3h1
fT# T@@ @ 	@
 c@ @ 
@P #% .2 c 	
     DcN+ 
,0# 0(3- 0Xs Xt Xt_ _D _Xd^ _0Z9 Z9c Z9hsm Z9x3 8C= &)t )T )d )V2H 2H 2HhSP SP3 SPQYZ]Q^ SPjm SPr 
c  
s  
tTWY\T\~  
Dp8t p8RU p8dS U4RUCV=W D %)@
@
 @
 	@

 SM@
 
c3h@
N %)33 3 	3
 SM3j  $)C )C )Vc hsm "@B@B @B 	@B
 @B 
@BL %)	vv v SM	v
 
c3hvx %)	EE E SM	E Er3   r   )rS  r   r?   r=  r&  r  r  r   typingr   r   r   r   r   r  r	   stage_detectorr   instruction_builderr   guideline_managerr   r   r   r3   r0   <module>r\     s?    
      	 3 3  ) 3 /i ir3   