
    .cj                    X    d Z ddlmZ ddlZddlmZ ddlmZ dd
ZdZ	ddZ
ddddZdS )u  Post-loop turn finalization for ``run_conversation``.

Extracted from ``agent/conversation_loop.py`` as part of the god-file
decomposition campaign (``~/.hermes/plans/god-file-decomposition.md``, Phase 1
step 4 — the post-loop ``TurnFinalizer`` seam). ``run_conversation``'s tail
(everything after the main tool-calling ``while`` loop) is lifted here verbatim:
budget-exhaustion summary, trajectory save, session persist, turn diagnostics,
response transforms, result-dict assembly, steer drain, and the memory/skill
review trigger.

Behavior-neutral: the body is moved unchanged. All ``agent.*`` side effects fire
exactly as before; only the post-loop *locals* are passed in as keyword args, and
the assembled ``result`` dict is returned to ``run_conversation`` which returns it
to the caller. The function is synchronous with a single return — mirroring the
region it replaces (no awaits, no early returns).

Module ``logger`` is imported lazily inside the body (``from
agent.conversation_loop import logger``) so this module never imports
``agent.conversation_loop`` at import time -> no import cycle, and the log records
keep the exact logger name (``"agent.conversation_loop"``).
    )annotationsN)_summarize_user_message_for_log)flatten_message_textmsgdictreturnboolc                    |                      d          sdS t          |                      d                                                     S )u  An assistant row with ``tool_calls`` but no visible text content of its own.

    Such a row satisfies the role check (``tail role == "assistant"``) while
    carrying none of the delivered answer — see the #43849/#44100 invariant
    block in :func:`finalize_turn`. Uses :func:`flatten_message_text` so that
    multimodal (list-type) content is evaluated by its text parts, not just
    its type.
    
tool_callsFcontent)getr   strip)r   s    6/home/ice/.hermes/hermes-agent/agent/turn_finalizer.py_is_pure_tool_call_tailr      sF     77<   u#CGGI$6$677==????    )_verification_stop_synthetic_pre_verify_syntheticNonec                (    d | D             | dd<   dS )zRemove verification-continuation nudge messages from *messages* in place.

    Only the synthetic nudges carry these flags, so this strips just the
    nudges while preserving the real attempted-final-answer that was
    persisted to state.db.
    c                ~    g | ]9t          t                    r t          fd t          D                       7:S )c              3  B   K   | ]}                     |          V  d S )N)r   ).0fms     r   	<genexpr>zI_drop_verification_continuation_scaffolding.<locals>.<listcomp>.<genexpr>A   s-      +_+_AEE!HH+_+_+_+_+_+_r   )
isinstancer   any _VERIFICATION_CONTINUATION_FLAGSr   r   s    @r   
<listcomp>z?_drop_verification_continuation_scaffolding.<locals>.<listcomp>?   s_       1d##(++_+_+_+_>^+_+_+_(_(_	  r   N )messagess    r   +_drop_verification_continuation_scaffoldingr#   8   s,       HQQQKKKr   F)_pending_verification_response(_pending_verification_response_previewedc               
   ddl m} || j        k    p| j        j        dk    }|o| o| ot          |          dv }|du ot          |          o|}d}d}|r|}|rd| _        d| d| j         d	}d}d}ns|q|rod| d| j         d	}|                     d
| d| j         d           | j	        s!| 
                    d| d| j         d           |                     ||          }d}|rt          j                            d          }|r	 ddlm} |                                }	 |                    ||d| d| j         dddd|| j        d           |                    d||| j                   	 |                                 n:# t*          $ r Y n.w xY w# 	 |                                 w # t*          $ r Y w w xY wxY wn(# t*          $ r |                    d|d           Y nw xY wt          |                              d          }|duo| o|| j        k     p|}t1          | dd          }|du r~t3          |t4                    rit3          |t                    sTt1          | dd          durAt1          | dd          0t1          | j        dd          }t9          |          r ||           g }	 |                     |t=          |	          |           nG# t*          $ r:}|                    d|            |                     d|d           Y d}~nd}~ww xY w	 | !                    |           nG# t*          $ r:}|                    d|            |                     d |d           Y d}~nd}~ww xY w	 | "                    |           tG          |           |rdd!l$m%}  |||           |r|s	 |r|d"         nd} n# t*          $ r d} Y nw xY wt3          | tL                    r|                     d#          nd}!|!d$k    r|                    d$|d%           nXt3          | tL                    rC|                     d&          |k    r*tO          |           r|| d&<   | (                    d'd           t1          | d(d          }"t9          |"          r |"|           | )                    ||           nG# t*          $ r:}#|                    d)|#            |                     d*|#d           Y d}#~#nd}#~#ww xY w|r|d"                             d#          nd}$d}%|$d+k    rtU          |          D ]}&|&                    d#          d$k    rk|&                    d,          rV|&d,         }'|'rJt3          |'d         tL                    r/|'d"                             d-i                               d.          }% ntW          d/ |D                       }(|rtY          |          nd})| j        r| j        j-        nd}*| j        r| j        j.        nd}+d0},|| j/        || j        |*|+|(|$|)| j0        pd1f
}-|$d+k    r|s |j        d2|,z   d3z   g|-|%R   n |j        |,g|-R   |r|s	 t1          | d4d          pi }.|.rE| 1                                r1| 2                    |.          }/|/r|3                                d5z   |/z   }n-# t*          $ r }0|4                    d6|0           Y d}0~0nd}0~0ww xY w|s	 | 5                                r|pd76                                }1|1d7k    p|1d8k    }2|2 oD| oAt          |                              d9           otY          |1          d:k    o|1d"d         d;v}3t          |          d<k    }4|2s|3s|4r$| 7                    |          }5|5r|2r|5}n|1d5z   |5z   }n-# t*          $ r }6|4                    d=|6           Y d}6~6nd}6~6ww xY wd}7|r|s	 dd>l8m9}8  |8d?|| j0        pd7| j/        t1          | d@d          pd7A          }9|9D ]}:t3          |:t
                    r|:r|:}d}7 n n-# t*          $ r };|                    dB|;           Y d};~;nd};~;ww xY w|rs|sq	 dd>l8m9}8  |8dC| j0        |||
|tu          |          | j/        t1          | d@d          pd7D	  	         n-# t*          $ r };|                    dE|;           Y d};~;nd};~;ww xY w	 ddFl m;}< t1          | dGd          }= |<| ||=|||||||H
  
         n-# t*          $ r };|                    dI|;           Y d};~;nd};~;ww xY wd}>tU          |          D ]U}?|?                    d#          dJk    r n9|?                    d#          d$k    r|?                    dK          r
|?dK         }> nVi dL|dM|>dN|dO|dP|dQ|dR|dSddT|dU|7dVt1          | dWd          dX| j/        dY| j<        dZ| j=        d[| j>        d\| j?        d]| j@        | jA        | jB        | jC        | jD        | jE        t1          | j        d^d          pd| jF        | jG        | jH        t1          | d_i           pi                     d`          pi                     da          | j0        db}@| jI        | jI        J                                |@dc<   |r||@dd<   | K                                }A|Ar|A|@de<   d| _        |r| jL        r
| jL        |@df<   | M                                 d| _N        d}B| jO        dk    r"| jP        | jO        k    rdg| jQ        v r	d}Bd| _P        | R                    |
|||h           |r=|s;|s|Br7	 | S                    tu          |          ||Bi           n# t*          $ r Y nw xY w	 dd>l8m9}8  |8dj| j0        ||||| j/        t1          | d@d          pd7k           n-# t*          $ r };|                    dl|;           Y d};~;nd};~;ww xY wd| _T        d| _U        |@S )mzRun the post-loop finalization and return the turn ``result`` dict.

    Lifted verbatim from ``run_conversation`` (the region after the main agent
    loop). See module docstring.
    r   )logger>   unknownbudget_exhaustedNFTzmax_iterations_reached(/)u#   ⚠️ Iteration budget exhausted (u   ) — asking model to summariseu%   
⚠️  Iteration budget exhausted (u   ) — requesting summary...HERMES_KANBAN_TASK)	kanban_dbzIteration budget exhausted (u;   ) — task could not complete within the allowed iterations	timed_out)budget_used
budget_max)erroroutcomerelease_claimend_runevent_payload_extraz5recorded budget-exhausted failure for task %s (%d/%d)z5Failed to record budget-exhausted failure for task %s)exc_infoztext_response( _turn_preflight_display_snapshot _turn_received_provider_responsecontext_compressor-rollback_interrupted_preflight_display_tokenszsave_trajectory: z*finalize_turn: _save_trajectory failed: %szcleanup_task_resources: z1finalize_turn: _cleanup_task_resources failed: %s)close_interrupted_tool_sequencerole	assistant)r=   r   r   _db_persisted$_apply_persist_user_message_overridezpersist_session: z*finalize_turn: _persist_session failed: %stoolr   functionnamec              3     K   | ]I}t          |t                    r2|                    d           dk    0|                    d          EdV  JdS )r=   r>   r      N)r   r   r   r   s     r   r   z finalize_turn.<locals>.<genexpr>t  sf        a#$55==K#?#?AEE,DWDW#? 	
#?#?#?#? r   zuTurn ended: reason=%s model=%s api_calls=%d/%d budget=%d/%d tool_turns=%d last_msg_role=%s response_len=%d session=%snonez>Turn ended with pending tool result (agent may appear stuck). z last_tool=%s_turn_failed_file_mutationsz

z(file-mutation verifier footer failed: %s z(empty)text_response   >      。   ！   ？!r+   .?`partial_stream_recoveryz$turn-completion explainer failed: %s)invoke_hooktransform_llm_outputplatform)response_text
session_idmodelrU   z$transform_llm_output hook failed: %spost_llm_call)rW   task_idturn_iduser_messageassistant_responseconversation_historyrX   rU   zpost_llm_call hook failed: %s)$_notify_context_engine_turn_complete_last_turn_usage)usager'   r[   rZ   api_call_countinterruptedfailedturn_exit_reasonz(on_turn_complete notification failed: %suser	reasoningfinal_responselast_reasoningr"   	api_calls	completedre   rd   partialrc   response_transformedresponse_previewed_response_was_previewedrX   providerbase_urlinput_tokensoutput_tokenscache_read_tokenslast_prompt_tokensrequest_overrides
extra_bodyservice_tier)cache_write_tokensreasoning_tokensprompt_tokenscompletion_tokenstotal_tokensru   estimated_cost_usdcost_statuscost_sourcerx   rW   	guardrailcleanup_errorspending_steerinterrupt_messageskill_manage)original_user_messagerh   rc   r"   )messages_snapshotreview_memoryreview_skillson_session_end)rW   rZ   r[   rk   rc   rX   rU   zon_session_end hook failed: %s)Vagent.conversation_loopr'   max_iterationsiteration_budget	remainingstrr	   ro   _emit_status
quiet_mode_safe_print_handle_max_iterationsosenvironr   
hermes_clir-   connect_record_task_failureinfoclose	Exceptionwarning
startswithgetattrr   intr9   callable_save_trajectoryr   appendr1   _cleanup_task_resources)_drop_trailing_empty_response_scaffoldingr#   agent.message_sanitizationr;   r   r   pop_persist_sessionreversedsumlenused	max_totalrX   rW   _file_mutation_verifier_enabled$_format_file_mutation_failure_footerrstripdebug"_turn_completion_explainer_enabledr   #_format_turn_completion_explanationhermes_cli.pluginsrS   listr_   rp   rq   session_input_tokenssession_output_tokenssession_cache_read_tokenssession_cache_write_tokenssession_reasoning_tokenssession_prompt_tokenssession_completion_tokenssession_total_tokenssession_estimated_cost_usdsession_cost_statussession_cost_source_tool_guardrail_halt_decisionto_metadata_drain_pending_steer_interrupt_messageclear_interrupt_stream_callback_skill_nudge_interval_iters_since_skillvalid_tool_names_sync_external_memory_for_turn_spawn_background_reviewr7   r8   )Cagentrh   rb   rc   rd   r"   r^   effective_task_idr[   r\   r   _should_review_memory_turn_exit_reasonr$   r%   r'   r)   budget_fallback_eligiblecontinuation_budget_exhaustediteration_limit_fallbackpreserved_verification_fallback_kanban_task_kb_connnormal_text_responserk   _preflight_snapshot_rollback_fn_cleanup_errors	_save_err_cleanup_errr;   _tail
_tail_role_apply_override_persist_err_last_msg_role_last_tool_name_m_tcs_turn_tool_count	_resp_len_budget_used_budget_max	_diag_msg
_diag_args_failedfooter_ver_err	_stripped_is_empty_terminal_is_partial_fragment_is_partial_stream_recovery_explanation_exp_err_response_transformed_invoke_hook_transform_results_hook_resultexcr_   _turn_usageri   r   result_leftover_steer_should_review_skillssC                                                                      r   finalize_turnr   E   sv   . /..... 	%.. 	1!+q0 
 	 	FO	FJ	F !""&EE	  	$ 	%/00	%$ "  %&+#$ ( 8 4 	1,0E)^n^^uG[^^^#' *.''		$<	 _n^^uG[^^^,. , ,5CW , , ,	
 	
 	
  	, , ,%J^ , , ,   55hOO#'  / z~~&:;; $	#777777,,$) .) )161E) ) )
 !,&* $+9*/*>- - -   " KKO$ne6J  
$   $      K !       011<<=MNNd" 	
J	
 U11 $# * "14  	t*C00 	.55 	 E=uEETQQE/66B$;
 

 L!! 	.L,--- O]x)H)V)VXabbbb ] ] ]>9>>???A9W[\\\\\\\\]
g%%&78888 g g gH,HHIIIH,aeffffffffgY`77AAA 	4H===   	FRRRRRR++HnEEE"  !	1+ !	1(0:d   .8.E.EO6***4J[((  P PQQQQE4(( 1UYYy-A-A^-S-SXopuXvXv-S $2i  		/4000 "%)OQUVVO$$ 	&OH%%%x)=>>>> ` ` `A<AABBBA<Z^________` 2:CXb\%%f---tNO8$$ 	 	Bvvf~~,,1E1E,,' OJtAw55 O&*2hll:r&B&B&F&Fv&N&NO       (6<N###1I272HO5)..aL6;6LS%(22RSK	D 
 	5;8Lk.)"F	J L)*	
 	
 )	
 	
 	
 	
 	
 	I+
++++"  Ok O	Oe%BDIIORG O5@@BB OCCGLL O%3%:%:%<%<v%E%NN 	O 	O 	OLLCXNNNNNNNN	O&  'K&	K7799 #+1r88::	%."_%N	Y8N"
 +* ];;] 122==oNNN] I",] ""##.\\ % )**.GG , '+ 3
 $)#L#L)$ $L $ - 
 .:NN !*F 2\ A +  	K 	K 	KLL?JJJJJJJJ	K "  Hk H	HFFFFFF!-&, +1rk 
D99?R" " " !3  lC00 \ %1N,0)E 	H 	H 	HNNA3GGGGGGGG	H  Ak A	AFFFFFFL +)2#1%)(^^k 
D99?R
 
 
 
 
  	A 	A 	ANN:C@@@@@@@@	AHPPPPPP e%7>>,,%)#.	
 	
 	
 	
 	
  H H HA3GGGGGGGGH N!!  776??f$$E776??k))cggk.B.B) -NE!.!.! 	H! 	^	!
 	Y! 	-! 	&! 	5! 	{! 	 5! 	ge-FNN! 	! 	EN! 	EN! 	2!  	4!!" 	U<#!$ $>!:4"<2%e&>@TVWXX]\]#>00 U/44:??MMSQS
#n

&A! ! !FD *6#AMMOO{  3#2  0022O 2"1$)E!  ?u/ ?&+&>"# 
 "E "#a''(E,GGG%"888 $#$  
((3%	 )     k /D H] 	**"&x..33 +    
  	 	 	D	>BBBBBB'%#+UJ55;		
 		
 		
 		
 		
  > > >7========> .2E*-2E*Ms  G 'AF 5F
 	G 

FG FG GF10G1
F>;G=F>>GG "G*)G*9$K 
L"(0LL"&L< <
N 0M;;N <S O S OS OC'S 
T	0TT	0A[ 
[5[00[5;B;^7 7
_!__!+Aa 
a+a&&a+3Ab6 6
c  cc $,d 
d;d66d;%n 
nn4o 
o2o--o2)r   r   r   r	   )r   r   )__doc__
__future__r   r   agent.codex_responses_adapterr   agent.message_contentr   r   r   r#   r   r!   r   r   <module>r     s    , # " " " " " 				 I I I I I I 6 6 6 6 6 6@ @ @ @&$  
 
 
 
8 $(-2!l	 l	 l	 l	 l	 l	 l	r   