
    H|j-                         d Z ddlZddlmZmZ ddlmZmZmZ ddl	m
Z
 ddlmZ ddlmZ ddlmZ dd	lmZmZ  ej(                  e      Zd
Z G d dee      Zy)u  scene_camera_flow StepRunner — 씬 단위 카메라 연속 이동 경로 설계.

shot_staging 이전에 실행되어, 선택된 샷들을 씬 관통 카메라 플로우 위에 배정한다.
shot_staging은 이 플로우에서 개별 샷 카메라를 파생시킨다.
    N)ThreadPoolExecutoras_completed)AnyDictList)AppError)
StepRunner)_DetailStepMixin)call_structured)load_promptload_schema   c            
       P    e Zd ZdZdefdZddeeef   fdZde	dedede	de	f
d	Z
y
)SceneCameraFlowStepuW   씬 단위 카메라 연속 흐름 설계 — 선택된 샷을 플로우 위에 배정.returnc                 H   ddl }ddl}ddlm} |j	                         }|j                  t        dd      j                  d             |j                  d       |j                  t        dd      j                  d             |j                  d       |j                  |j                  t        dd	      d
      j                  d             |j                  d       |j                   || j                        j                  d             |j                         dd S )u0  실제 로드되는 effective prompt(system/user/schema)의 내용 해시를
        접는다 — 같은 팩 내 내용 변경도 CP 무효화 (shot_staging 관례 동형).

        2026-08-12 카메라 문법 팩 v3 발행에서 드러난 구멍: 기본 config_hash
        는 프로젝트 설정만 봐서, 팩을 올려도 완료 스텝이 clean SKIP 되고
        하류 staging 이 **구 flow 를 계승**해 팩 효과가 무력화된다(정면·정적
        수렴의 발원지가 flow 라 이 스텝의 재실행이 수정의 성패 지점이다).r   N)compute_config_hashscene_camera_flowsystemzutf-8    userschemaT)	sort_keys   )hashlibjsonapp.core.step_runnerr   sha256updater   encodedumpsr   project_config	hexdigest)selfr   _jsonr   hs        [/Users/manta/Documents/Projects/TheRoad-I1/backend/app/core/steps/scene_camera_flow_step.py_config_hashz SceneCameraFlowStep._config_hash   s     	<NN	0(;BB7KL		0&9@@IJ		+X6$  

&/	 	
	$T%8%89@@IJ{{}Sb!!    c                 
   | j                  d      }|r!|j                  di       j                  d      st        ddd      |d   d   }|D ci c]  }|j                  dd	      | }}| j                  d
      }| j                  d      }|r|st        ddd      |j                  di       j                  d      st        ddd      d	dlm}  ||| j
                  d       | j                  d      }	|	r!|	j                  di       j                  d      st        ddd      | j                  d      }
|
r|
j                  d      st        ddd      i }|j                  di       j                  d      xs g D ]#  }t        |j                  dg             ||d   <   % i }|d   d   D ]  }|d   }|j                  dg       ||<    i }|	r|	j                  di       j                  d      ri }|
r\|
j                  d      rKdD ]F  }|
d   j                  |g       D ],  }|j                  dd      }|s|j                  dd      ||<   . H |	d   d   D ]_  }|j                  d      }|j                  dg       xs g }|D cg c]&  }|j                  |      s|j                  |d      ( }}|||<   a t        dd      }t        dd      }t        dd      }| j                  d      }i }|d k(  ry|rw|j                  di       j                  d      rV|d   d   D ]*  }|j                  d      }|j                  d!      s&|||<   , |rt        j                  d"t        |             g }g }d	}d	}d	} t        |j                               D ]  \  }}!|j                  |t                     }"|!D #cg c]  }#|#j                  d#      |"v s|# }$}#|!D #cg c]  }#|#j                  d#      |"vs|# }%}#|$s|j                  |d$g g d%       |d&z  }||v r|j                  ||          |d&z  }|j                  ||$|%|j                  |i       |j                  |g       d'        |rt        t         (      5 }&|D 'ci c]%  }'|&j#                  | j$                  |'|||      |'d   ' }(}'t'        |(      D ]?  })|)j)                         }*|*j                  d!      r|d&z  }n| d&z  } |j                  |*       A 	 d d d        |j+                  d) *       ||z   | z   }+||z   |+| d|i| j-                         d+S c c}w c c}w c c}#w c c}#w c c}'w # 1 sw Y   XxY w),N
scene_savedatasegmentszstep.no_inputu8   scene_save 체크포인트 누락 또는 segments 없음i  )codemessagestatus_codescene_indexr   shot_validatorshot_selectionu0   shot_extract 또는 shot_selection 결과 없음scenesu(   shot_extract data.scenes가 비어있음)assert_no_failed_scenesr   )consumer_stepscene_directoru:   scene_director 체크포인트 누락 또는 scenes 없음entity_mergeu#   entity_merge 체크포인트 누락selected_shot_indicesshots)
characters	locationspropsshort_id namevisible_entity_idsr   r   r   resumeflow_stagesz0scene_camera_flow resume: %d scenes already done
shot_indexu)   선택된 샷 없음 — 플로우 없음r1   flow_summaryrC   shot_assignments   )r1   selected_shotsunselected_shotssegentities)max_workersc                 &    | j                  dd      S )Nr1   r   )get)rs    r'   <lambda>z.SceneCameraFlowStep._execute.<locals>.<lambda>   s    }a)@r)   )key)completed_countapplicable_countfailed_countr,   config_hash)_load_prev_checkpointrO   r   "app.core.steps.shot_validator_stepr5   r"   setr   r   loggerinfolensorteditemsappendr   MAX_WORKERSsubmit_process_scener   resultsortr(   ),r$   modescene_save_cpr-   rK   seg_by_sceneshot_extract_cpshot_selection_cpr5   scene_director_cpentity_merge_cpselected_mapscall_shots_by_scenesientity_names_by_scene
id_to_nameetypeesidvisiblevnamessystem_promptuser_templater   existing_cpexisting_oktasksscene_results	processedskippedfailed	all_shotsselshrI   rJ   pooltaskfuturesfutrc   totals,                                               r'   _executezSceneCameraFlowStep._execute1   s   22<@M$5$5fb$A$E$Ej$Q$R 
 !(4S[(\S[C)BC)GS[(\445EF 667GH&7$J 
 ""62.228<$B 
 	O1D1DTgh 667GH (9(=(=fb(I(M(Mh(W$T 
 44^Do&9&9&&A$=  (*$((488BHbHB.1"&&9PRT2U.VLM*+ I 57!&)(3BM"B%'VVGR%8r" 4
 79!2!6!6vr!B!F!Fx!P)+J?#6#6v#>AE,V488CeeJ3./eeFB.?JsO D B
 (/9VVM*&&!5r:@b8?U1:>>RSCT2.U,1%b)	 : $$7B#$7@0(; 001DE')80K0O0OPX0Y!&)(3VVM*66-(&(KO 4 NPST_P`a $&	#$6$<$<$>?MB	""2su-C+4T9R|8LPS8Sb9NT-6ZYr"&&:NVY:YYZ!$$#%$O#%(*	&  1[ $$[_5Q	LL!"0$4#''B/155b"= ) @8 #<
 !&	 !& KK++T=-QWM*+ !&	   (0C ZZ\Fzz-0!Q	!!((0 1 = 	@AG#f,  )72 %"}-  ,,.
 	
G )]t V8 UZ6 =<sI   UU	%U	>UU!U:UU*U6AUUU&r   rx   ry   r   c                     |d   }|d   }|d   }|d   }|d   }	|j                  dd      }
|j                  dd      }g }|D ]9  }|j                  d	|j                  d
d       d|j                  dd              ; |rdj                  |      nd}g }|D ]9  }|j                  d	|j                  d
d       d|j                  dd              ; |rdj                  |      nd}|	rdj                  |	      nd}|j                  ||
||||      }dd l}|j                  |      }|D cg c]  }|d
   	 }}|rd|d|d   d   d   d   d
<   	 t        d|||| j                  d| | j                  d|i            }||d<   t        j                  d|t        |j                  dg             t        |j                  dg                    |S c c}w # t        $ r+}t        j                  d||       |d | g g d!cY d }~S d }~ww xY w)"Nr1   rI   rJ   rK   rL   headingr?   textz  Shot rD   ?z: description
u
     (없음)z, u   (엔티티 정보 없음))r1   scene_heading
scene_textselected_shots_blockunselected_shots_blockentities_blockr   integer)typeenum
propertiesrG   r^   r   scene_camera_flow_)extra_metadata)steprx   user_promptresponse_schemar"   schema_nameopik_metadataz5scene_camera_flow S%d: %d stages, %d shot assignmentsrC   z scene_camera_flow S%d failed: %su   분석 실패: rE   )rO   r_   joinformatcopydeepcopyr   r"   build_opik_metadatarZ   r[   r\   	Exceptionerror)r$   r   rx   ry   r   ro   rI   rJ   rK   entity_namesr   r   	sel_linesr   selected_blockunsel_linesunselected_blockr   r   r   call_schemaselected_indicesrc   excs                           r'   rb   z"SceneCameraFlowStep._process_scene   st   - ./ 235kJ'	2.WWVR(
	 B"&&s34BrvvmR7P6QR ! 2;9-"B"&&s34BrvvmR7P6QR # 6A499[1l4@<0Fa#**'!!/#3) + 
 	mmF+7EF~B|,~F!(bK%&89'B<PQ]^
	$(+' +#2205"66}VXFY6ZF %'F=!KKGFJJ}b12FJJ1267	 M1 G2  	LL;RE!"1# 7!$&	 	s%   -GBG 	H" HHHN)rB   )__name__
__module____qualname____doc__strr(   r   r   r   dictrb    r)   r'   r   r      sX    a"c "2U
c3h U
nF4 F FC FY] Fbf Fr)   r   )r   loggingconcurrent.futuresr   r   typingr   r   r   app.core.errorsr   r   r	   app.core.steps.detail_stepsr
   app.modules.llm.llm_clientr   app.modules.prompt_loaderr   r   	getLoggerr   rZ   r`   r   r   r)   r'   <module>r      sO   
  ? " " $ + 8 6 >			8	$y*J yr)   