
    FjWX                        d Z ddlmZ ddlZddlZddlZddlmZ ddlm	Z	m
Z
mZ  ej        e          Zddd&dZ eh d          Zd'd(dZd)dZddddddd*dZd+d,d#Zd'd,d$Zg d%ZdS )-u  Codex API runtime — App Server and Responses-API streaming paths.

Extracted from :class:`AIAgent` to keep the agent loop file focused.
Each function takes the parent ``AIAgent`` as its first argument
(``agent``).  AIAgent keeps thin forwarder methods for backward
compatibility.

* ``run_codex_app_server_turn`` — drives one turn through the
  ``codex_app_server`` subprocess client (used when a Codex CLI install
  is the active provider).
* ``run_codex_stream`` — streams a Codex Responses API call (the
  ``codex_responses`` api_mode).
* ``run_codex_create_stream_fallback`` — recovery path when the
  Responses ``stream=True`` initial create fails.
    )annotationsN)SimpleNamespace)AnyDictListF)should_review_memoryuser_messagestroriginal_user_messager   messagesList[Dict[str, Any]]effective_task_idr   boolreturnDict[str, Any]c          	        ddl m} t          | d          r| j        Zt	          | dd          pt          j                    }	 ddlm}  |            }	n# t          $ r d}	Y nw xY w |||	          | _        	 | j        
                    |          }
n}# t          $ rp}t                              d	           	 | j                                         n# t          $ r Y nw xY wd| _        d
| d|dddt          |          dcY d}~S d}~ww xY wt	          |
dd          rRt                              d|
j                   	 | j                                         n# t          $ r Y nw xY wd| _        |
j        r|                    |
j                   t	          | dd          |
j        z   | _        d}| j        dk    r"| j        | j        k    rd| j        v r	d}d| _        |
j        sR|
j        K	 |                     ||
j        d           n,# t          $ r t                              dd           Y nw xY w|
j        r^|
j        sW|s|rS	 |                     t9          |          ||           n,# t          $ r t                              dd           Y nw xY w|
j        |d|
j         o|
j        du |
j        p|
j        du|
j        |
j        |
j        dS )aN  Codex app-server runtime path. Hands the entire turn to a `codex
    app-server` subprocess and projects its events back into Hermes'
    messages list so memory/skill review keep working.

    Called from run_conversation() when agent.api_mode == "codex_app_server".
    Returns the same dict shape as the chat_completions path.
    r   )CodexAppServerSession_codex_sessionNsession_cwd)_get_approval_callback)cwdapproval_callback)
user_inputzcodex app-server turn failedzCodex app-server turn failed: z:. Fall back to default runtime with `/codex-runtime auto`.FT)final_responser   	api_calls	completedpartialerrorshould_retirez1codex app-server session retired (turn error: %s)_iters_since_skillskill_manage)r   r   interruptedzexternal memory sync raisedexc_info)messages_snapshotreview_memoryreview_skillszbackground review spawn raised   )r   r   r   r   r   r   codex_thread_idcodex_turn_id))agent.transports.codex_app_server_sessionr   hasattrr   getattrosgetcwdtools.terminal_toolr   	Exceptionrun_turnlogger	exceptioncloser
   warningr   projected_messagesextendtool_iterationsr    _skill_nudge_intervalvalid_tool_namesr"   _sync_external_memory_for_turn
final_textdebug_spawn_background_reviewlist	thread_idturn_id)agentr	   r   r   r   r   r   r   r   r   turnexcshould_review_skillss                2/usr/local/lib/hermes-agent/agent/codex_runtime.pyrun_codex_app_server_turnrH      s.     POOOOO
 5*++ 
u/C/Ke]D11@RY[[	%BBBBBB 6 6 8 8 	% 	% 	% $	%44/ 
  
  

#,,,EE 
 
 
7888	 &&(((( 	 	 	D	#L L L L !XX

 

 
	
 
	
 
	
 
	
 
	
 
	

4 t_e,, 	$?J	
 	
 	
	 &&(((( 	 	 	D	#
  1/000 	+Q//$2FF 
 !#a''$(CCCe444##$   G
 2	G00&;#! 1    
  	G 	G 	GLL6LFFFFF	G 	J J "J &:J
	J**"&x..22 +    
  	J 	J 	JLL9DLIIIII	J /))@djD.@#=tz'=>	 	 	s   A A#"A#9B 
DD
:CD

C!D
 C!!#D
D
DE 
E+*E+2H &H98H9%I5 5&JJ>   response.failedresponse.completedresponse.incompleteeventnamedefaultc                    t          | |d          }|+t          | t                    r|                     ||          }||n|S )zSField access that handles both attr-style (SDK objects) and dict (raw JSON) events.N)r-   
isinstancedictget)rL   rM   rN   values       rG   _event_fieldrT      sH    E4&&E}E400}		$((%5572    Nonec                    ddl m} t          | dd          pd                                } ||t          | d          t          | d                    )	zRaise a ``_StreamErrorEvent`` from a ``type=error`` SSE frame.

    Imported lazily so this module stays importable from places that don't
    pull in ``run_agent`` (e.g. plugin code, doc tools).
    r   )_StreamErrorEventmessage zstream emitted error eventcodeparam)r[   r\   )	run_agentrX   rT   strip)rL   rX   rY   s      rG   _raise_stream_errorr_      sp     ,+++++E9b11Q5QXXZZG

%((5'**   rU   )on_text_deltaon_reasoning_deltaon_first_deltaon_eventinterrupt_check
event_itermodelr   c          
     4   g }g }d}	d}
d}d}d}d}d}d}| D ]n}|J	  ||           n=# t           t          f$ r  t          $ r t                              dd           Y nw xY w| |            r nt          |dd          }t          |t                    sd}|d	k    rt          |           d
|v s|dk    rt          |dd          }|r|	                    |           |	sy|
s<d}
|8	  |             n,# t          $ r t                              dd           Y nw xY w|9	  ||           n,# t          $ r t                              dd           Y nw xY wJd|v rd}	d|v rTd|v rPt          |dd          }|r;|9	  ||           n,# t          $ r t                              dd           Y nw xY w|dk    r)t          |d          }||	                    |           |t          v rd}t          |d          }|Vt          |dd          }|*t          |t                    r|                    d          }t          |dd          }|*t          |t                    r|                    d          }|}t          |dd          }|*t          |t                    r|                    d          }t          |t                    r|}|dk    r=t          |dd          }|*t          |t                    r|                    d          }|dk    r=t          |d	d          }|*t          |t                    r|                    d	          }|dk    r|pd}n|dk    r|pd}n
|dk    r|pd} np|rt          |          }n@|r<|	s:d                    |          }t!          dddt!          d |!          g"          g}ng }|s|st#          d#          d                    |          }t!          ||||||||$          }|S )%ud  Consume a Codex Responses SSE event stream and return a final response.

    The returned object is a ``SimpleNamespace`` shaped like the SDK's typed
    ``Response`` for the fields downstream code actually reads:

    * ``output``: list of output items, assembled from ``response.output_item.done``.
      For tool-call turns this contains the function_call items; for plain-text
      turns it contains a synthesized ``message`` item built from streamed deltas
      if no message item was emitted directly.
    * ``output_text``: assembled text from ``response.output_text.delta`` deltas.
    * ``usage``: copied from the terminal event's ``response.usage`` (when present).
    * ``status``: ``completed`` / ``incomplete`` / ``failed`` (or ``completed`` if
      the stream ended without a terminal frame but produced content).
    * ``id``: ``response.id`` when present.
    * ``incomplete_details``: passed through for ``response.incomplete`` frames.
    * ``error``: passed through for ``response.failed`` frames.
    * ``model``: from kwargs (the wire model name is not authoritative).

    Critically, we never read ``response.output`` from the terminal event for
    content reconstruction — only ``usage``, ``status``, ``id``.  That field
    being ``null`` / ``[]`` / missing is fine.

    Callbacks:

    * ``on_text_delta(str)`` — fires per ``response.output_text.delta``, suppressed
      once a function_call event is seen (so tool-call turns don't bleed text
      into the chat).
    * ``on_reasoning_delta(str)`` — fires per ``response.reasoning.*.delta``.
    * ``on_first_delta()`` — one-shot, fires on the first text delta only.
    * ``on_event(event)`` — fires for every event before any other processing.
      Used for watchdog activity, debug logging, anything wire-shape-agnostic.
    * ``interrupt_check()`` — returns True to break the loop early.
    Fr   Nz!Codex stream on_event hook raisedTr#   typerZ   r   zoutput_text.deltazresponse.output_text.deltadeltaz"Codex stream on_first_delta raisedz!Codex stream on_text_delta raisedfunction_call	reasoningz&Codex stream on_reasoning_delta raisedzresponse.output_item.doneitemresponseusageidstatusrK   incomplete_detailsrI   rJ   
incompletefailedrY   	assistantoutput_text)rh   text)rh   rolerp   contentz7Codex Responses stream did not emit a terminal response)outputru   rn   rp   ro   rf   rq   r   )TimeoutErrorInterruptedErrorr1   r3   r>   rT   rP   r
   r_   append_TERMINAL_EVENT_TYPESr-   rQ   rR   r@   joinr   RuntimeError)re   rf   r`   ra   rb   rc   rd   collected_output_itemscollected_text_deltashas_tool_callsfirst_delta_firedterminal_statusterminal_usageterminal_response_idterminal_incomplete_detailsterminal_errorsaw_terminalrL   
event_type
delta_textreasoning_text	done_itemresp_objridrstatusry   	assembledassembled_textfinals                                rG   _consume_codex_event_streamr      s   V )+')N&ON $'+NL _ _	Q "23     Q Q Q @4PPPPPQ &??+<+<&E!%44
*c** 	J   &&&*,,
>Z0Z0Z%eWb99J ]%,,Z888% ], b,0))5b . 0 0 0 0#, b b b &-Q\` a a a a ab$0])M*5555( ] ] ]"LL)LW[L\\\\\]j((!N *$$J)>)>)%"==N Z"4"@Z&&~6666  Z Z ZLL!ITXLYYYYYZ444$UF33I$&--i888...L#E:66H#!(7D!A!A!)j4.H.H)%-\\'%:%:Nhd33;:h#=#=;",,t,,C'*$!(Hd;;?z(D'A'A?&ll844Ggs++ .&-O!66629(DXZ^2_2_/2:z(TX?Y?Y:6>llCW6X6X3!222%,Xw%E%EN%-*Xt2L2L-)1g)>)>111"1"@[444"1"A\000"1"=XE? /H  ,--	 	~ 	GG122	!$-iHHHI	
 
 
    
 
E
 
 	
 WW233N"6	 	 	E LsE   )7A#"A#-
C88&D! D!'D33&EEF&F:9F:
api_kwargsrQ   clientc                6    ddl }|p                     d          }d}g  _        d fd
}d fd}d fd}	d  fd}
t          |dz             D ]} j        rt          d          t          |          }d|d<   	  |j        j        d!i |}ng# |j	        |j
        |j        t          f$ rG}||k     r;t                              d|dz   |dz                                    |           Y d}~ d}~ww xY w	 t!          |d          rTt!          |d          sD|t#          |dd          }t%          |          r 	  |             c S # t&          $ r Y c S w xY wc S 	 t)          ||                    d          ||||	|
          }n# |j	        |j
        |j        t          f$ r}||k     rzt                              d|dz   |dz                                    |           Y d}~t#          |dd          }t%          |          r	  |             # t&          $ r Y w xY wՂ d}~ww xY w|j        dv r\t                              d|j        |j        |j        t5          d  j        D                                                                   |t#          |dd          }t%          |          r 	  |             c S # t&          $ r Y c S w xY wc S # t#          |dd          }t%          |          r	  |             w # t&          $ r Y w w xY ww xY wdS )"u  Execute one streaming Responses API request and return the final response.

    Uses ``responses.create(stream=True)`` (low-level raw event iteration)
    rather than the high-level ``responses.stream(...)`` helper.  This makes
    us structurally immune to backend drift in the ``response.completed``
    payload shape — we never let the SDK reconstruct a typed object from
    the terminal event's ``output`` field.
    r   Ncodex_stream_direct)reasonr(   rv   r
   r   rV   c                f    j                             |                                |            d S N)_codex_streamed_text_partsr|   _fire_stream_deltarv   rC   s    rG   _on_text_deltaz(run_codex_stream.<locals>._on_text_delta  s4    (//555  &&&&&rU   c                2                         |            d S r   )_fire_reasoning_deltar   s    rG   _on_reasoning_deltaz-run_codex_stream.<locals>._on_reasoning_delta  s    ##D)))))rU   rL   r   c                b    t          j                     _                            d           d S )Nzreceiving stream response)time_codex_stream_last_event_ts_touch_activity)rL   rC   s    rG   	_on_eventz#run_codex_stream.<locals>._on_event  s,    ,0IKK)9:::::rU   r   c                 ,    t           j                  S r   )r   _interrupt_requested)rC   s   rG   _interrupt_checkz*run_codex_stream.<locals>._interrupt_check  s    E.///rU   z+Agent interrupted before Codex stream retryTstreamzLCodex Responses stream connect failed (attempt %s/%s); retrying. %s error=%sry   __iter__r5   rf   )rf   r`   ra   rb   rc   rd   z\Codex Responses stream transport failed mid-iteration (attempt %s/%s); retrying. %s error=%s>   rs   rr   zbCodex Responses stream terminal status=%s (incomplete_details=%s, error=%s, streamed_chars=%d). %sc              3  4   K   | ]}t          |          V  d S r   )len).0ps     rG   	<genexpr>z#run_codex_stream.<locals>.<genexpr>  s(      II1AIIIIIIrU   )rv   r
   r   rV   rL   r   r   rV   )r   r    )httpx_ensure_primary_openai_clientr   ranger   r{   rQ   	responsescreateRemoteProtocolErrorReadTimeoutConnectErrorConnectionErrorr3   r>   _client_log_contextr,   r-   callabler1   r   rR   rp   r6   rq   r   sum)rC   r   r   rb   _httpxactive_clientmax_stream_retriesr   r   r   r   attemptstream_kwargsevent_streamrE   close_fnr   s   `                rG   run_codex_streamr     s    _eAAI^A__M-/E$' ' ' ' ' '* * * * * *; ; ; ; ; ;
0 0 0 0 0 0 +a/00 > >% 	R"#PQQQZ(("&h
	9=29JJMJJLL*F,>@SUde 	 	 	+++baK!3a!7--//  
 	+	 |X.. $w|Z7X7X $#D |Wd;;H!! HJJJJJJ    DDD  C3 $..11"0':#1&$4   .0BFDWYhi 	 	 	///LLA!%7!%;1133S	   HHH |Wd;;H!! HJJJJ    D 	 |777OL%":EKII(HIIIII--//   |Wd;;H!! HJJJJJJ    DDD   |Wd;;H!! HJJJJ    Du> >s   ?BC6/<C10C11C6:!K<
E		
EE)F	K	H,&<H'"K
H
H! H!&H''H,,A)K6
K
KK!L:
LL
L	LL	Lc                &    t          | ||          S )a  Backward-compatible alias for the unified event-driven path.

    Historically this was the fallback when the SDK's high-level
    ``responses.stream(...)`` helper raised on shape drift.  The primary
    path now does exactly what the fallback did, so this just forwards.
    Kept as a public symbol because tests and a small number of call sites
    still reference it by name.
    )r   )r   )rC   r   r   s      rG    run_codex_create_stream_fallbackr     s     E:f====rU   )rH   r   r   r   )r	   r
   r   r   r   r   r   r
   r   r   r   r   r   )rL   r   rM   r
   rN   r   r   r   r   )re   r   rf   r
   r   r   )NN)r   rQ   r   r   )__doc__
__future__r   loggingr.   r   typesr   typingr   r   r   	getLogger__name__r3   rH   	frozensetr}   rT   r_   r   r   r   __all__r   rU   rG   <module>r      s}     # " " " " "  				  ! ! ! ! ! ! " " " " " " " " " "		8	$	$ "'Q Q Q Q Q QV "	 # # #   3 3 3 3 3   & ~ ~ ~ ~ ~ ~B] ] ] ] ]@	> 	> 	> 	> 	>  rU   