
    PmjБ                    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    :/home/thesage/.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%           n_t3          | tL                    rJ|                     d&          |k    r1tO          |           r"|| d&<   | (                    d'd           d| _)        t1          | d(d          }"t9          |"          r |"|           |s|s	 t1          | dd          }#|#rt1          |#d)d          du rt9          t1          |#d*d                    r|rt1          | d+d          stU          |          }$|#+                    |          }%t1          |#d,d          rd|#_,        d| _)        t3          |%tZ                    r	|%r|%|dd<   tU          |          }&|$|&k    r|                    d-|$|&           n-# t*          $ r }'|                    d.|'           Y d}'~'nd}'~'ww xY w| .                    ||           nG# t*          $ r:}(|                    d/|(            |                     d0|(d           Y d}(~(nd}(~(ww xY w|r|d"                             d#          nd})d}*|)d1k    rt_          |          D ]}+|+                    d#          d$k    rk|+                    d2          rV|+d2         },|,rJt3          |,d         tL                    r/|,d"                             d3i                               d4          }* nta          d5 |D                       }-|rtU          |          nd}.| j        r| j        j1        nd}/| j        r| j        j2        nd}0d6}1|| j3        || j        |/|0|-|)|.| j4        pd7f
}2|)d1k    r|s |j        d8|1z   d9z   g|2|*R   n |j        |1g|2R   |r|s	 t1          | d:d          pi }3|3rE| 5                                r1| 6                    |3          }4|4r|7                                d;z   |4z   }n-# t*          $ r }5|8                    d<|5           Y d}5~5nd}5~5ww xY w|s	 | 9                                r|pd=:                                }6|6d=k    p|6d>k    }7|7 oD| oAt          |                              d?           otU          |6          d@k    o|6d"d         dAv}8t          |          dBk    }9|7s|8s|9r$| ;                    |          }:|:r|7r|:}n|6d;z   |:z   }n-# t*          $ r };|8                    dC|;           Y d};~;nd};~;ww xY wd}<|r|s	 ddDl<m=}=  |=dE|| j4        pd=| j3        t1          | dFd          pd=G          }>|>D ]}?t3          |?t
                    r|?r|?}d}< n n-# t*          $ r }@|                    dH|@           Y d}@~@nd}@~@ww xY w|rs|sq	 ddDl<m=}=  |=dI| j4        |||
|t[          |          | j3        t1          | dFd          pd=J	  	         n-# t*          $ r }@|                    dK|@           Y d}@~@nd}@~@ww xY w	 ddLl m>}A t1          | dMd          }B |A| ||B|||||||N
  
         n-# t*          $ r }@|                    dO|@           Y d}@~@nd}@~@ww xY wd}Ct_          |          D ]U}D|D                    d#          dPk    r n9|D                    d#          d$k    r|D                    dQ          r
|DdQ         }C nVi dR|dS|CdT|dU|dV|dW|dX|dYddZ|d[|<d\t1          | d]d          d^| j3        d_| j?        d`| j@        da| jA        db| jB        dc| jC        | jD        | jE        | jF        | jG        | jH        t1          | j        ddd          pd| jI        | jJ        | jK        t1          | dei           pi                     df          pi                     dg          | j4        dh}E| jL        | jL        M                                |Edi<   |rt          |          djk    r|pdk|Edl<   |r||Edm<   | N                                }F|Fr|F|Edn<   d| _        |r| jO        r
| jO        |Edo<   | P                                 d| _Q        d}G| jR        dk    r"| jS        | jR        k    rdp| jT        v r	d}Gd| _S        | U                    |
|||q           |r=|s;|s|Gr7	 | V                    t[          |          ||Gr           n# t*          $ r Y nw xY w	 ddDl<m=}=  |=ds| j4        ||||||| j3        t1          | dFd          pd=t
  
         n-# t*          $ r }@|                    du|@           Y d}@~@nd}@~@ww xY wd| _W        d| _X        |ES )vzRun 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_override_micro_compact_enabled_micro_compact_persist_disabled_flush_scan_cursor_invalidatedz#Micro-compaction: %d -> %d messageszMicro-compaction failed: %sz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>  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modelrY   z$transform_llm_output hook failed: %spost_llm_call)r[   task_idturn_iduser_messageassistant_responseconversation_historyr\   rY   zpost_llm_call hook failed: %s)$_notify_context_engine_turn_complete_last_turn_usage)usager'   r_   r^   api_call_countinterruptedfailedturn_exit_reasonz(on_turn_complete notification failed: %suser	reasoningfinal_responselast_reasoningr"   	api_calls	completedri   rh   partialrg   response_transformedresponse_previewed_response_was_previewedr\   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_tokensry   estimated_cost_usdcost_statuscost_sourcer|   r[   	guardrailsession_persistence_faileduF   session storage could not be written — free disk space and try againr1   cleanup_errorspending_steerinterrupt_messageskill_manage)original_user_messagerl   rg   r"   )messages_snapshotreview_memoryreview_skillson_session_end)	r[   r^   r_   ro   rh   rg   ri   r\   rY   zon_session_end hook failed: %s)Yagent.conversation_loopr'   max_iterationsiteration_budget	remainingstrr	   rs   _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_db_flush_scan_prefixlenrB   rD   list_persist_sessionreversedsumused	max_totalr\   r[   _file_mutation_verifier_enabled$_format_file_mutation_failure_footerrstripdebug"_turn_completion_explainer_enabledr   #_format_turn_completion_explanationhermes_cli.lifecyclerW   rc   rt   ru   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   )Hagentrl   rf   rg   rh   r"   rb   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_responsero   _preflight_snapshot_rollback_fn_cleanup_errors	_save_err_cleanup_errr;   _tail
_tail_role_apply_override_compressor_before
_compacted_after_mc_err_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excrc   _turn_usagerm   r   result_leftover_steer_should_review_skillssH                                                                           r   finalize_turnr  E   s;   . /..... 	%.. 	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S`77AAA 	4H===   	FRRRRRR++HnEEE"  '	3+ '	3(0:d   .8.E.EO6***4J[((  P PQQQQE4(( 3UYYy-A-A^-S-SXopuXvXv-S $2i  		/4000 /3+ "%)OQUVVO$$ 	&OH%%%  ,	D6 ,	D+D%e-A4HH  "-EuMMQUUU 6F!M!MNN V& V $E+>FF V "(mmG!,!;!;H!E!EJ #%Eu  ; FKB6:3!*d33 1
 1&0 ]]F&((A#V    D D D97CCCCCCCCD 	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HHHHHH!-&, +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HHHHHH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{  
#'((,HHH( 
T 	w  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	>DDDDDD'%#.+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 <W% O W% OW% OCW% <C$V!  W% !
W+WW% WW% %
X)/0X$$X)A_+ +
`5``B;c 
d!c<<dAe! !
f+ffAg 
h  g;;h ,h1 1
i;ii%r> >
s
s6t 
t0t++t0)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!o
 o
 o
 o
 o
 o
 o
r   