
    NQjKF                        d Z ddlmZ ddlZddlZddlZddlmZmZ ddl	m
Z
 ddlmZ ddlmZ d%d&dZd%d'dZd%d(dZ	 	 	 	 d)d*dZd Z	 	 	 	 d+d,d"Zd%d-d$ZdS ).u  Oneshot (-z) mode: send a prompt, get the final content block, exit.

Bypasses cli.py entirely.  No banner, no spinner, no session_id line,
no stderr chatter.  Just the agent's final text to stdout.

Toolsets = explicit --toolsets when provided, otherwise whatever the user has
configured for "cli" in `hermes tools`.
Rules / memory / AGENTS.md / preloaded skills = same as a normal chat turn.
Approvals = auto-bypassed (HERMES_YOLO_MODE=1 is set for the call).
Working directory = the user's CWD (AGENTS.md etc. resolve from there as usual).

Model / provider selection mirrors `hermes chat`:
    - Both optional. If omitted, use the user's configured default.
    - If both given, pair them exactly as given.
    - If only --model given, auto-detect the provider that serves it.
    - If only --provider given, error out (ambiguous — caller must pick a model).

Env var fallbacks (used when the corresponding arg is not passed):
    - HERMES_INFERENCE_MODEL
    )annotationsN)redirect_stderrredirect_stdout)Path)Optional)get_fallback_chaintoolsetsobjectreturnlist[str] | Nonec                   | sd S t          | t                    r| gn| }t          |t          t          f          s|g}g }|D ]~}t          |t                    r3|                    d |                    d          D                        J|                    t          |                                                     d |D             pd S )Nc              3  >   K   | ]}|                                 V  d S N)strip).0parts     6/home/alina/.hermes/hermes-agent/hermes_cli/oneshot.py	<genexpr>z&_normalize_toolsets.<locals>.<genexpr>-   s*      GGtdjjllGGGGGG    ,c                    g | ]}||S  r   )r   items     r   
<listcomp>z'_normalize_toolsets.<locals>.<listcomp>1   s    000T40D000r   )
isinstancestrlisttupleextendsplitappendr   )r	   	raw_items
normalizedr   s       r   _normalize_toolsetsr$   "   s     t(377E

XIi$//  K	J 1 1dC   	1GGtzz#GGGGGGGc$iioo//000000Z0008D8r   #tuple[list[str] | None, str | None]c                   t          |           }|dS 	 ddlm n# t          $ r}d d| dfcY d }~S d }~ww xY wfd|D             fd|D             }|rW	 ddlm}  |             fd	|D             n# t          $ r g Y nw xY wr#                               fd
|D             }t          d D                       rFd |D             }|r6t          j	        
                    dd                    |           d           dS t                      t                      |r	 ddlm} ddlm}  |            }t#          |                    d          t&                    r|                    d          ni }	|	                                D ]\  }
}t#          |t&                    s ||                    dd          d          r#                    t-          |
                     _                    t-          |
                     n,# t          $ r t                      t                      Y nw xY wfd|D             }fd|D             }fd|D             }|z   }|r6t          j	        
                    dd                    |           d           |r6t          j	        
                    dd                    |           d           |sdS |d fS )N)NNr   )validate_toolsetz*hermes -z: failed to validate --toolsets: 
c                *    g | ]} |          |S r   r   r   namer'   s     r   r   z/_validate_explicit_toolsets.<locals>.<listcomp>>   s*    FFF/?/?/E/EFFFFr   c                    g | ]}|v|	S r   r   )r   r+   built_ins     r   r   z/_validate_explicit_toolsets.<locals>.<listcomp>?   s#    FFF4X1E1E$1E1E1Er   )discover_pluginsc                *    g | ]} |          |S r   r   r*   s     r   r   z/_validate_explicit_toolsets.<locals>.<listcomp>F   s*    RRRT;K;KD;Q;QRDRRRr   c                    g | ]}|v|	S r   r   )r   r+   plugin_valids     r   r   z/_validate_explicit_toolsets.<locals>.<listcomp>L   s#    RRR4\9Q9Q$9Q9Q9Qr   c              3     K   | ]}|d v V  	dS )>   *allNr   r   r+   s     r   r   z._validate_explicit_toolsets.<locals>.<genexpr>N   s'      
5
5D4<
5
5
5
5
5
5r   c                    g | ]}|d v|	S )>   r3   r4   r   r5   s     r   r   z/_validate_explicit_toolsets.<locals>.<listcomp>O   s"    KKKD$l2J2J42J2J2Jr   zNhermes -z: --toolsets all enables every toolset; ignoring additional entries: z, )read_raw_config)_parse_enabled_flagmcp_serversenabledT)defaultc                    g | ]}|v |	S r   r   )r   r+   	mcp_namess     r   r   z/_validate_explicit_toolsets.<locals>.<listcomp>k   s#    BBB$	0A0A0A0A0Ar   c                    g | ]}|v |	S r   r   )r   r+   mcp_disableds     r   r   z/_validate_explicit_toolsets.<locals>.<listcomp>l   s#    DDDt|/C/C/C/C/Cr   c                $    g | ]}|v|v
|S r   r   )r   r+   r?   r=   s     r   r   z/_validate_explicit_toolsets.<locals>.<listcomp>m   s.    aaad).C.CT`H`H`tH`H`H`r   z0hermes -z: ignoring unknown --toolsets entries: zThermes -z: ignoring disabled MCP servers (set enabled: true in config.yaml to use): )Nz:hermes -z: --toolsets did not contain any valid toolsets.
)r$   r	   r'   	Exceptionhermes_cli.pluginsr.   r   anysysstderrwritejoinsethermes_cli.configr7   hermes_cli.tools_configr8   r   getdictitemsaddr   )r	   r#   exc
unresolvedr.   ignoredr7   r8   cfgr9   r+   
server_cfg	mcp_validdisabledunknownvalidr-   r?   r=   r1   r'   s                   @@@@@r   _validate_explicit_toolsetsrX   4   s    $X..JzJ------- J J JI#IIIIIIIIIIJ GFFFFFFHFFFF:FFFJ S	;;;;;;RRRRZRRRLL 	 	 	LLL	  	SOOL)))RRRR:RRRJ

5
5H
5
5
555 KKJKKK 	JG04		'0B0BG G G   z%%I UUL !	!999999CCCCCC!/##C4>sww}?U?UW[4\4\d#''-000bdK$/$5$5$7$7 0 0 j!*d33 &&z~~i'F'FPTUUU 0MM#d)),,,, $$SYY////0  	! 	! 	!I55LLL	! CBBB*BBBIDDDDDDDHaaaaa
aaaGy E d
bDIIV]L^L^bbbccc 

'yy""' ' '	
 	
 	

  SRR$;s9   ! 
=8==A> >BB4C+H   &I	I	pathOptional[str]resultrL   failureNonec                   | sdS 	 ddl }|                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d	          |                    d
          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          t          |                    d                    p|dud}|||d<   t          |                                           }|j                            dd           |                    |                    |d          dz   d           dS # t          $ r Y dS w xY w)u   Best-effort JSON usage report for pipelines (``-z --usage-file``).

    Written even on failure so callers can always account for spend. Never
    raises — a broken usage write must not mask the run's own outcome.
    Nr   estimated_cost_usdcost_statuscost_sourceinput_tokensoutput_tokenscache_read_tokenscache_write_tokensreasoning_tokenstotal_tokens	api_callsmodelprovider
session_id	completedfailed)r_   r`   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   rk   rl   rm   r\   T)parentsexist_ok   )indentr(   utf-8encoding)
jsonrK   boolr   
expanduserparentmkdir
write_textdumpsrA   )rY   r[   r\   ru   reportouts         r   _write_usage_filer~   ~   s      #)**-A"B"B!::m44!::m44"JJ~66#ZZ88!',?!@!@"(**-A"B"B &

+= > >"JJ~66K00ZZ((

:.. **\22K006::h//00GG44G
 
"  'F94jj##%%
555tzz&z33d:WMMMMM   s   F7F? ?
GGpromptr   ri   rj   
usage_fileintc           	        t          j        t           j                   t          j        dd                                          }|r9|pd                                s#|s!t          j                            d           dS t          |          \  }}|r!t          j                            |           dS t          |          du }dt          j        d<   dt          j        d<   t          j        }	t          j        }
t          t          j        d	d
          }d}i }d}	 t          |          5  t!          |          5  	 t#          | ||||          \  }}n# t$          $ r}|}Y d}~nd}~ww xY wddd           n# 1 swxY w Y   ddd           n# 1 swxY w Y   	 |                                 n:# t(          $ r Y n.w xY w# 	 |                                 w # t(          $ r Y w w xY wxY w|t+          |t,          t.          f          r!t1          ||t3          |                     |t1          ||t5          |                     |
                    d| d           |
                                 dS t1          ||           |rS|	                    |           |                    d          s|	                    d           |	                                 |                    d          s|                    d          r|pd                                sdS |pd                                s+|
                    d           |
                                 dS dS )u  Execute a single prompt and print only the final content block.

    Args:
        prompt: The user message to send.
        model: Optional model override. Falls back to HERMES_INFERENCE_MODEL
            env var, then config.yaml's model.default / model.model.
        provider: Optional provider override. Falls back to config.yaml's
            model.provider, then "auto".
        toolsets: Optional comma-separated string or iterable of toolsets.
        usage_file: Optional path; when set, a JSON usage report (estimated
            cost, token counts, model, api_calls) is written there after the
            run — even when the run fails — so pipelines can account for
            spend per invocation.

    Returns the exit code.  Caller should sys.exit() with the return.
    HERMES_INFERENCE_MODEL zhermes -z: --provider requires --model (or HERMES_INFERENCE_MODEL). Pass both explicitly, or neither to use your configured defaults.
rp   N1HERMES_YOLO_MODEHERMES_ACCEPT_HOOKSwrr   rs   )ri   rj   r	   use_config_toolsets)r\   zhermes -z: agent failed: r(      rm   partialzGhermes -z: no final response was produced; treating the run as failed.
r   )loggingdisableCRITICALosgetenvr   rD   rE   rF   rX   r$   environstdoutopendevnullr   r   
_run_agentBaseExceptioncloserA   r   KeyboardInterrupt
SystemExitr~   reprr   flushendswithrK   )r   ri   rj   r	   r   env_model_earlyexplicit_toolsetstoolsets_errorr   real_stdoutreal_stderrr   responser[   r\   rO   s                   r   run_oneshotr      s=   8 OG$%%% i 8"==CCEEO %+2,,.. / 
R	
 	
 	
 q(CH(M(M%~ 
(((q-h774? &)BJ!"(+BJ$% *K*K2:sW555G"HF$(GW%% 	 	w'?'? 	 	#-%.(;$ $ $ && !    	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	&	MMOOOO 	 	 	D		MMOOOO 	 	 	D	  g 1:>?? 	j&$w--HHHHM*fc'llCCCCAgAAABBBqj&))) (###  && 	$d###

8 

9 5 5 B?U?U?W?W qN!!## deeeq1s    G /F?E>EE>
E/#E*%E>*E//E>2F>F	FF	F	G FG FG !F6 6
GGG-GG-
G*'G-)G**G-c                 ~    	 ddl m}   |             S # t          $ r }t          j        d|           Y d}~dS d}~ww xY w)a!  Best-effort SessionDB for ``hermes -z`` / oneshot mode.

    Oneshot bypasses ``HermesCLI._init_agent()``, so it must wire the SQLite
    session store itself. Without this, the ``session_search``/recall tool is
    advertised but every call returns "Session database not available.".
    r   )	SessionDBz7SQLite session store not available for oneshot mode: %sN)hermes_stater   rA   r   debug)r   rO   s     r   _create_session_db_for_oneshotr     se    ******y{{   OQTUUUttttts    
<7<Tr   rv   tuple[str, dict]c                   ddl m} ddlm} ddlm} ddlm} ddlm	}	  |            }
|

                    d          pi }t          |t                    r|}n,|
                    d          p|
                    d          pd	}t          j        d
d	                                          }|pd	                                p|p|}|pd	                                pd}d}|m|s|rh|pd	                                p|}|rM	 ddlm} |                                 |j        
                    |                                                                          }n# t*          $ r d}Y nw xY w|0|j        }|j        }|j        r|j                            d          }nd	}t          |t4                    rHt          |
                    d          pd	                                                                          }|p:t          j        dd	                                                                          pd} |||          }|r|\  }} |||pd|          }t7          |          }||rt9           ||
d                    }t;                      }t=          |
          } |	|
                    d          |
                    d          |
                    d          |
                    d          ||dd||
                    d          |pdt>                    }d|_         d|_!        d|_"        |#                    |           }|
                    d          pd	|fS )zBuild an AIAgent exactly like a normal CLI chat turn would, then
    run a single conversation.  Returns ``(final_response, run_result)``.r   )load_config)detect_provider_for_model)resolve_runtime_provider)_get_platform_tools)AIAgentri   r;   r   r   N)model_switch/rj   HERMES_INFERENCE_PROVIDERauto)	requestedtarget_modelexplicit_base_urlcliapi_keybase_urlapi_modeTcredential_pool)r   r   rj   r   ri   enabled_toolsets
quiet_modeplatform
session_dbr   fallback_modelclarify_callbackfinal_response)$rI   r   hermes_cli.modelsr   hermes_cli.runtime_providerr   rJ   r   	run_agentr   rK   r   r   r   r   r   
hermes_clir   _ensure_direct_aliasesDIRECT_ALIASESlowerrA   ri   rj   r   rstriprL   r$   sortedr   r   _oneshot_clarify_callbacksuppress_status_outputstream_delta_callbacktool_gen_callbackrun_conversation)r   ri   rj   r	   r   r   r   r   r   r   rR   	model_cfg	cfg_model	env_modeleffective_modeleffective_providerexplicit_base_url_from_aliasexplicit_model_msdirectcfg_providercurrent_providerdetectedruntimetoolsets_listr   _fbagentr[   s                                r   r   r   )  s    .-----;;;;;;DDDDDD;;;;;;!!!!!!
+--C   &BI)S!! M		MM),,L	g0F0FL"		2B77==??I{))++EyEIO #.b//119T26 !u!	!  +2,,..;) 	C::::::**,,,+//0D0D0F0F0L0L0N0NOO   !"(,%+_"? O39?3I3I#3N3N0!i.. X#&y}}Z'@'@'FB#G#G#M#M#O#O#U#U#W#WL  y!<bAAGGIIOOQQ !
 54^EUVV C:B7&&&$$,6  G (11M!4223>>??/11J S
!
!CGI&&Z((Z((Z((&$566{d 3/  E8 $(E "&E"E##F++FJJ'((.B77s   AE E+*E+questionc                    |rd| dS 	 dS )uy   Clarify is disabled in oneshot mode — tell the agent to pick a
    default and proceed instead of stalling or erroring.z<[oneshot mode: no user available. Pick the best option from z' using your own judgment and continue.]z\[oneshot mode: no user available. Make the most reasonable assumption you can and continue.]r   )r   choicess     r   r   r     s;      
@@ @ @	

	, r   r   )r	   r
   r   r   )r	   r
   r   r%   )rY   rZ   r[   rL   r\   rZ   r   r]   )NNNN)r   r   ri   rZ   rj   rZ   r	   r
   r   rZ   r   r   )NNNT)r   r   ri   rZ   rj   rZ   r	   r
   r   rv   r   r   )r   r   r   r   )__doc__
__future__r   r   r   rD   
contextlibr   r   pathlibr   typingr   hermes_cli.fallback_configr   r$   rX   r~   r   r   r   r   r   r   r   <module>r      sj   * # " " " " "  				 



 7 7 7 7 7 7 7 7             9 9 9 9 9 99 9 9 9 9$G G G G GT" " " " "N  " $s s s s sl  $  " ${8 {8 {8 {8 {8|      r   