
    `gj2Q                        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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y)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)declare_stateless_channel)get_fallback_chainc                n   | sy t        | t              r| gn| }t        |t        t        f      s|g}g }|D ]b  }t        |t              r(|j	                  d |j                  d      D               ;|j                  t        |      j                                d |D cg c]  }|s|	 c}xs d S c c}w )Nc              3  <   K   | ]  }|j                           y wN)strip).0parts     E/root/.hermes/venv/lib/python3.12/site-packages/hermes_cli/oneshot.py	<genexpr>z&_normalize_toolsets.<locals>.<genexpr>.   s     GtdjjlGs   ,)
isinstancestrlisttupleextendsplitappendr   )toolsets	raw_items
normalizeditems       r   _normalize_toolsetsr   #   s    (37
XIi$/K	J 1dC Gtzz#GGc$ioo/0	1 (0T4D08D80s   B2'B2c                   t        |       }|y	 ddlm} |D cg c]  } ||      s| }}|D cg c]	  }||vs| }}|rM	 ddlm}  |        |D cg c]  } ||      s| }}|r%|j                  |       |D cg c]	  }||vs| }}t        d |D              rI|D cg c]	  }|dvs| }	}|	r2t        j                  j                  d	d
j                  |	       d       yt               }
t               }|r	 ddlm} ddlm}  |       }t#        |j%                  d      t&              r|j%                  d      ni }|j)                         D ]e  \  }}t#        |t&              s ||j%                  dd      d      r|
j+                  t-        |             L|j+                  t-        |             g 	 |D cg c]	  }||
v s| }}|D cg c]	  }||v s| }}|D cg c]  }||
vs||vs| }}||z   }|r2t        j                  j                  dd
j                  |       d       |r2t        j                  j                  dd
j                  |       d       |sy|d fS # t        $ r}d d| dfcY d }~S d }~ww xY wc c}w c c}w c c}w # t        $ r g }Y Gw xY wc c}w c c}w # t        $ r t               }
t               }Y w xY wc c}w c c}w c c}w )N)NNr   )validate_toolsetz*hermes -z: failed to validate --toolsets: 
)discover_pluginsc              3  $   K   | ]  }|d v  
 yw)>   *allN )r   names     r   r   z._validate_explicit_toolsets.<locals>.<genexpr>O   s     
5D4<
5s   >   r$   r%   zNhermes -z: --toolsets all enables every toolset; ignoring additional entries: z, )read_raw_config)_parse_enabled_flagmcp_serversenabledT)defaultz0hermes -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.configr(   hermes_cli.tools_configr)   r   getdictitemsaddr   )r   r   r    excr'   built_in
unresolvedr"   plugin_validignored	mcp_namesmcp_disabledr(   r)   cfgr*   
server_cfg	mcp_validdisabledunknownvalids                        r   _validate_explicit_toolsetsrH   5   s   $X.JJ- ",F/?/EFHF#-F4X1E$FJF	;-7RT;KD;QDRLR OOL)+5R4\9Q$RJR

5H
55$.KD$l2J4KKJJ004		'0B/C2G %I UL	!9C!#C4>sww}?UW[4\#''-0bdK$/$5$5$7 0 j!*d3&z~~i'FPTUMM#d), $$SY/0 #-B$	0ABIB!+Dt|/CDHD *ad).CT`H`taGay E

KDIIV]L^K__abc

byy"#2'	

 R$;A  JA#bIIIJ GF S 	L	
 S L0  	!I5L	! CDas   I6 JJ	JJJ# J$J(J# 	J5J5'	J:1J:B=J? 	K#K#	K(#K(-	K-7K-<K-6	J?JJJJ# #J21J2?K K c                \   | sy	 ddl }i d|j                  d      d|j                  d      d|j                  d      d|j                  d      d|j                  d      d|j                  d      d	|j                  d	      d
|j                  d
      d|j                  d      d|j                  d      d|j                  d      d|j                  d      d|j                  d      d|j                  d      dt        |j                  d            xs |dud|j                  d      }|||d<   t        |       j	                         }|j
                  j                  dd       |j                  |j                  |d      dz   d       y# t        $ r Y y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service_tierfailureT)parentsexist_ok   )indentr!   utf-8encoding)
jsonr7   boolr   
expanduserparentmkdir
write_textdumpsr-   )pathresultrZ   rb   reportouts         r   _write_usage_filerm      s     
 &**-A"B
6::m4
 6::m4
 FJJ~6	

 VZZ8
  ,?!@
 !&**-A"B
 

+= >
 FJJ~6
 K0
 VZZ(
 

:.
 &**\2
 K0
 d6::h/0GG44G
* FJJ~6+
.  'F94j##%

5tzz&z3d:WM s   FF 	F+*F+c           	     $   t        j                  t         j                         t        j                  dd      j                         }|r6|xs dj                         s"|s t        j                  j                  d       yt        |      \  }}|r t        j                  j                  |       yt        |      du }dt        j                  d<   dt        j                  d<   t                t        j                  }	t        j                  }
t        t        j                  d	d
      }d}i }d}	 t!        |      5  t#        |      5  	 t%        | ||||      \  }}ddd       ddd       	 |j)                          |lt-        |t.        t0        f      rt3        ||t5        |             |t3        ||t7        |             |
j                  d| d       |
j9                          yt3        ||       |rC|	j                  |       |j;                  d      s|	j                  d       |	j9                          |j=                  d      s|j=                  d      r|xs dj                         sy|xs dj                         s"|
j                  d       |
j9                          yy# t&        $ r}|}Y d}~_d}~ww xY w# 1 sw Y   ixY w# 1 sw Y   nxY w# t*        $ r Y lw xY w# 	 |j)                          w # t*        $ r Y w w xY wxY w)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.  The caller owns process termination.
    HERMES_INFERENCE_MODEL zhermes -z: --provider requires --model (or HERMES_INFERENCE_MODEL). Pass both explicitly, or neither to use your configured defaults.
r]   N1HERMES_YOLO_MODEHERMES_ACCEPT_HOOKSwr_   r`   )rT   rU   r   use_config_toolsets)rZ   zhermes -z: agent failed: r!      rX   partialzGhermes -z: no final response was produced; treating the run as failed.
r   )loggingdisableCRITICALosgetenvr   r0   r1   r2   rH   r   environr   stdoutopendevnullr   r   
_run_agentBaseExceptioncloser-   r   KeyboardInterrupt
SystemExitrm   reprr   flushendswithr7   )promptrT   rU   r   
usage_fileenv_model_earlyexplicit_toolsetstoolsets_errorru   real_stdoutreal_stderrr   responserj   rZ   r;   s                   r   run_oneshotr      s   8 OOG$$% ii 8"=CCEO%+2,,./

R	
 (CH(M%~

(-h74? &)BJJ!"(+BJJ$%  **K**K2::sW5G"HF$(GW% 	w'? 	#-%.(;$ &	 	&	MMO  g 1:>?j&$w-HM*fc'lC5gYbABj&)(#  &d#

8

9 5B?U?U?WN!!#deU !  	 	 	 	*  			MMO 		s   0K- ;KK	J*K$K- -K *	K 3J;5K;K  KK	KKK- 	K*)K*-L/L ?L 	L	LLLc                 v    	 ddl m}   |        S # t        $ r }t        j                  d|       Y d}~y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   r-   rx   debug)r   r;   s     r   _create_session_db_for_oneshotr   )  s5    *{ OQTUs    	838c                	   ddl m} ddlm} ddlm} ddlm} ddlm	}	  |       }
|
j                  d      xs i }t        |t              r|}n(|j                  d      xs |j                  d      xs d	}t        j                  d
d	      j                         }|xs d	j                         xs |xs |}|xs d	j                         xs d}d}|F|s|rA|xs d	j                         xs |}|r&	 ddlm} |j%                          |j&                  j                  |j                         j)                               }|@|j,                  }|j.                  }|j0                  r|j0                  j3                  d      }nd	}t        |t4              r:t        |j                  d      xs d	      j                         j)                         }|xs6 t        j                  dd	      j                         j)                         xs d} |||      }|r|\  }} |||xs d|      }t7        |      }||rt9         ||
d            }t;               }d}	 t=        |
      } |	|j                  d      |j                  d      |j                  d      |j                  d      ||dd||j                  d      |xs dt>              }d|_         d|_!        d|_"        |jG                  |       }|j                  d      xs d	|f|Q	 tI        |dd      }t        |tJ              r|jM                  |       n|jM                          	 |jS                          |	 |jS                          S S # t*        $ r d}Y 9w xY w# t*        $ r tO        jP                  dd       Y Zw xY w# t*        $ r tO        jP                  dd       Y ow xY w# t*        $ r tO        jP                  dd       Y S w xY w# |	 tI        |dd      }t        |tJ              r|jM                  |       n|jM                          n&# t*        $ r tO        jP                  dd       Y nw xY w	 |jS                          n&# t*        $ r tO        jP                  dd       Y nw xY w|8	 |jS                          w # t*        $ r tO        jP                  dd       Y w w xY ww xY w)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)AIAgentrT   r,   rp   ro   N)model_switch/rU   HERMES_INFERENCE_PROVIDERauto)	requestedtarget_modelexplicit_base_urlcliapi_keybase_urlapi_modeTcredential_pool)r   r   rU   r   rT   enabled_toolsets
quiet_modeplatform
session_dbr   fallback_modelclarify_callbackfinal_response_session_messagesz%oneshot memory/context cleanup failed)exc_infozoneshot agent cleanup failedz$oneshot session store cleanup failed)*r5   r   hermes_cli.modelsr   hermes_cli.runtime_providerr   r6   r   	run_agentr   r7   r   r   r{   r|   r   
hermes_clir   _ensure_direct_aliasesDIRECT_ALIASESlowerr-   rT   rU   r   rstripr8   r   sortedr   r	   _oneshot_clarify_callbacksuppress_status_outputstream_delta_callbacktool_gen_callbackrun_conversationgetattrr   shutdown_memory_providerrx   r   r   )r   rT   rU   r   ru   r   r   r   r   r   rB   	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   agent_fbrj   session_messagess                                 r   r   r   9  s    .;D;!
-C  &BI)S!	MM),L	g0FL"			2B7==?I{))+EyEIO #.b//19T26 !u	  +2,,.;):**,++//0D0D0F0L0L0NO !"(,,%+__"??39??3I3I#3N0!i.#&y}}Z'@'FB#G#M#M#O#U#U#WL  yy!<bAGGIOOQ !
 5^EUV:B7&&$$,6G (1M!423>?/1J
 E@U !%KK	*[[,[[,[[,!*!#KK(9:;$ 7/
8 (,$&*#"&''/

+,2F;
 V#*52Et#L .5223CD224M !U  " "G  t  VEPTUV  M<tLM  UDtTU' V#*52Et#L .5223CD224 VEPTUVM M<tLM
 !U  " UDtTU "s   4AM, B.O0 ?M>N$O
,M;:M;> N! N!$ OO
 O-,O-0S4?P43S4 QSQSQ,+S, RSRSR&%S& S	SS		Sc                    |rd| dS 	 y)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&   )questionchoicess     r   r   r     s'     Ji>@	

	,    r   )r   objectreturnzlist[str] | None)r   r   r   z#tuple[list[str] | None, str | None])ri   Optional[str]rj   r8   rZ   r   r   None)NNNN)r   r   rT   r   rU   r   r   r   r   r   r   int)NNNT)r   r   rT   r   rU   r   r   r   ru   rc   r   ztuple[str, dict])r   r   r   r   )__doc__
__future__r   rx   r{   r0   
contextlibr   r   pathlibr   typingr   gateway.session_contextr   hermes_cli.fallback_configr	   r   rH   rm   r   r   r   r   r&   r   r   <module>r      s   * #  	 
 7   = 99$GT(Z  " $||| | 	|
 | 	|~$  " $[U[U[U [U 	[U
 [U [U|r   