
    .cjQ                    ^   U 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	 dZ
dZdd	d
ddd
gZded<   ddd
Zded<   dZded<   dFdZdGdZdGdZdHdZdIdZdJd ZdHd!ZdHd"ZdKd$ZdLdMd'Zd(d)dNd-ZdOd.ZdPd1ZdQd3ZdRd4ZdRd5ZdSd7Z dTdUd9Z!dVd;Z"dUd<Z#dWdXd?Z$dYdBZ%dWdZdDZ&d[dEZ'dS )\z:Mixture-of-Agents configuration and slash-command helpers.    )annotationsN)deepcopy)Any__HERMES_MOA_TURN_V1__defaultzopenai-codexzgpt-5.5providermodel
openrouterzdeepseek/deepseek-v4-prozlist[dict[str, str]]DEFAULT_MOA_REFERENCE_MODELSzanthropic/claude-opus-4.8zdict[str, str]DEFAULT_MOA_AGGREGATORfloat | NoneDEFAULT_MOA_REFERENCE_TIMEOUTreturnlist[dict[str, Any]]c                 >    d t          t                    D             S )Nc                    g | ]
}i |d diS )enabledT ).0slots     7/home/ice/.hermes/hermes-agent/hermes_cli/moa_config.py
<listcomp>z-_default_reference_models.<locals>.<listcomp>   s(    YYY$%t%Y%%YYY    )r   r   r   r   r   _default_reference_modelsr      s    YY(;W2X2XYYYYr   valuer   c                f    | | dk    rdS 	 t          |           S # t          t          f$ r Y dS w xY w)uF  Coerce to a float, or None when unset/blank/invalid.

    Used for optional sampling params (reference_temperature /
    aggregator_temperature) where None means 'don't send the parameter —
    provider default applies', matching how a single-model Hermes agent
    never sends temperature unless explicitly configured.
    N )float	TypeError
ValueError)r   s    r   _coerce_float_or_noner"      sN     }tU||z"   tts    00c                    | | dk    st          | t                    rt          S 	 t          |           }n# t          t
          f$ r
 t          cY S w xY wt          j        |          r|dk    rt          S |S )u  Return a finite positive advisor timeout, or None to inherit.

    ``None`` (the default) means "no per-preset override": the reference
    fan-out inherits the ``auxiliary.moa_reference.timeout`` config value
    (900s by default) via ``call_llm``'s own resolution, exactly like every
    other auxiliary task. An explicit finite positive per-preset value is
    honored as-is — no artificial cap, since long-thinking advisor models
    legitimately run far beyond five minutes.
    Nr   r   )
isinstanceboolr   r   r    r!   mathisfinite)r   timeouts     r   _coerce_reference_timeoutr)   /   s     }z%'>'>,,-,,z" - - -,,,,-=!! -W\\,,Ns   6 AAstrc                |    t          | pd                                                                          }|dv r|ndS )zENormalize failed-advisor disclosure policy; unknown values fail loud.loud>   r,   silentr*   striplower)r   policys     r   !_coerce_degraded_reference_policyr2   D   s@    &!!''))//11F11166v=r   intc                    | | dk    r|S 	 t          |           S # t          t          f$ r; 	 t          t          |                     cY S # t          t          f$ r |cY cY S w xY ww xY w)Nr   r3   r    r!   r   )r   r   s     r   _coerce_intr6   J   s    }5zzz"   	uU||$$$$$:& 	 	 	NNNNN	s,    A'AA'A#A'"A##A'
int | Nonec                    | | dk    rdS 	 t          |           }nN# t          t          f$ r: 	 t          t          |                     }n# t          t          f$ r Y Y dS w xY wY nw xY w|dk    r|ndS )u   Coerce to a positive int, or None when unset/blank/invalid/non-positive.

    Used for optional caps (e.g. reference_max_tokens) where None means
    'no cap' — the safe default that preserves prior uncapped behavior.
    Nr   r   r5   )r   ns     r   _coerce_int_or_noner:   V   s     }tJJz"   	E%LL!!AA:& 	 	 	444	 A
 A114s2    A'A
A'A!A' A!!A'&A'c                   t          | t                    rt          |                     d          pd                                                                          }|dk    r8t          |                     d          d          }|dk    rd| S |dk    rd	nd
S |} t          | pd                                                                          }|dv r|S |                    d          rR|                    d          \  }}}|r"t          |                                d          nd}|dk    rd| S |dk    rd	S d
S )up  Normalize the fan-out cadence; unknown values fall back to default.

    Canonical values are the strings ``per_iteration``, ``user_turn``, and
    ``every_n:<N>`` (N >= 2). The ``every_n`` cadence also accepts the mapping
    form ``{mode: every_n, n: N}`` from hand-edited YAML and normalizes it to
    the canonical string, so the rest of the pipeline (presets, flattened
    view, runtime) only ever sees one shape. ``every_n:1`` semantically means
    "run every iteration" and collapses to ``per_iteration``; anything
    unparseable falls back to ``user_turn`` (the default — cheapest cadence;
    see #67199).
    moder   every_nr9   r      zevery_n:   per_iteration	user_turn>   rA   r@   :)	r$   dictr*   getr/   r0   r6   
startswith	partition)r   r<   r9   _seprests         r   _coerce_fanoutrJ   h   sL    % 	 599V$$*++113399;;9EIIcNNA..AAvv%!~~%&'1ff??+=u{!!##))++D---y!! #~~c**3,/6K

a(((Q66!a>>!66"?;r   c                    | du rdS | | du rdS t          |                                                                           }|dv r|S |dv rdS dS )u  Normalize ``moa.privacy_filter`` to '' (off), 'display', or 'full'.

    - ``''`` (empty string): filter off — the default. ``false``/``None``/
      unknown values land here so a hand-edited config degrades to prior
      behavior (tolerant-read contract).
    - ``'display'``: redact user-visible surfaces only — the reference blocks
      shown in the UI and the saved MoA trace records. The aggregator still
      sees raw advisor text, so answer quality is unaffected.
    - ``'full'``: additionally redact the advisor text injected into the
      aggregator prompt (issue #59959's literal ask). A hand-edited boolean
      ``true`` maps here because the issue framed the toggle as "redact
      before passing to the aggregator".
    TfullNFr   >   rL   display>   1onyestruer.   )r   r<   s     r   coerce_privacy_filterrR      sn     }}v}ru::##%%D""")))v2r   
str | Nonec                    ddl m} | | du rdS  ||           }|dS |                    d          du rdS |                    d          S )	zIReturn a canonical per-slot reasoning effort, or None when unset/invalid.r   )parse_reasoning_effortNTr   Fnoneeffort)hermes_constantsrU   rD   )r   rU   parseds      r   _clean_reasoning_effortrZ      sn    777777}t##E**F~tzz)%%v::hr   Tr%   c                    | |S t          | t                    r| S t          | t                    r4|                                                                 }|dv rdS |dv rdS |S t          |           S )N>   0noofffalseF>   rN   rO   rP   rQ   T)r$   r%   r*   r/   r0   )r   r   texts      r   _coerce_boolra      s    }% % {{}}""$$...5---4;;r   Finclude_enabledr   rc   dict[str, Any] | Nonec               J   t          | t                    sd S t          |                     d          pd                                          }t          |                     d          pd                                          }|r|sd S |                                dk    rd S ||d}t          |                     d                    }|r||d<   t          |                     d                    }|||d<   |r&t          |                     d          d	          |d<   |S )
Nr	   r   r
   moar   reasoning_effort
max_tokensr   T)	r$   rC   r*   rD   r/   r0   rZ   r:   ra   )r   rc   r	   r
   cleanrW   slot_mts          r   _clean_slotrk      s0   dD!! t488J''-2..4466H!!'R((..00E 5 t ~~5  t)1EBBE$TXX.@%A%ABBF +$* ! "$((<"8"899G%l C'(;(;TBBiLr   c                d   t          | t                    sdS t          |                     d          pd                                          }t          |                     d          pd                                          }|s|sdS |sdS |sd| dS |                                d	k    rd
S dS )a/  Return a human-readable problem for a slot ``_clean_slot`` would drop.

    None means the slot is complete and valid. Mirrors ``_clean_slot`` exactly
    so the write-boundary validator (``validate_moa_payload``) and the
    tolerant runtime normalizer can never disagree about what is acceptable.
    z-must be an object with 'provider' and 'model'r	   r   r
   zprovider and model are requiredzprovider is requiredzmodel is required (provider 'z' has no model selected)rf   zMthe Mixture of Agents provider cannot be used inside a preset (recursive MoA)N)r$   rC   r*   rD   r/   r0   )r   r	   r
   s      r   _slot_problemrm      s     dD!! ?>>488J''-2..4466H!!'R((..00E 1E 100 &%% RQxQQQQ~~5  ^^4r   raw	list[str]c           
     d   t          | t                    sdgS |                     d          }t          |t                    r|r|}n	t          | i}g }|                                D ]G\  }}t          |pd                                          pd}t          |t                    s|                    d| d           Z|                    d          }t          |t                    st          |t                    r|gng }d}t          |          D ]=\  }	}
t          |
          }|r"|                    d| d	|	d
z    d|            8|d
z  }>|s|                    d| d           t          |                    d                    }|r|                    d| d|            I|S )ue  Return the problems ``normalize_moa_config`` would silently paper over.

    ``normalize_moa_config`` is deliberately tolerant: at *read* time a
    hand-edited config must degrade to defaults rather than crash the agent.
    That same tolerance at *write* time is a corruption engine — a client that
    sends a half-filled slot gets its whole preset silently replaced with the
    hardcoded defaults (#64156). API write paths call this first and reject
    invalid payloads loudly instead of saving something the user never chose.

    Returns a list of human-readable problems; empty means safe to save.
    zMoA config must be an objectpresetsr   z	(unnamed)zpreset 'z': must be an objectreference_modelsr   z' reference r?   z: z.': needs at least one complete reference model
aggregatorz' aggregator: )r$   rC   rD   DEFAULT_MOA_PRESET_NAMEitemsr*   r/   appendlist	enumeraterm   )rn   presets_rawrq   problemsnamepresetlabelrefscomplete_refsindexr   issue	agg_issues                r   validate_moa_payloadr      s    c4   0.//'')$$K+t$$ 1 1"- +C0H I IfDJB%%''6;&$'' 	OOBuBBBCCCzz,--$%% 	<'d33;D66D$T?? 	# 	#KE4!$''E # R5 R Reai R R5 R RSSSS" 	^OO\u\\\]]]!&**\":":;;	 	IOOGuGGIGGHHHOr   dict[str, Any]c                 b    t                      t          t                    d d t          ddd ddd
S )Nr,      rA   T)
rr   rs   reference_temperatureaggregator_temperaturereference_timeoutdegraded_reference_policyrh   reference_max_tokensfanoutr   )r   r   r   r   r   r   r   _default_presetr   (  s@    577566 "&"&:%+ $  r   c                $   t          | t                    si } |                     d          }t          |t                    r4	 t	          j        |          }n# t          j        t          f$ r g }Y nw xY wt          |t                    st          |t                    r|gng }d |D             }d |D             }|st                      }t          |                     d                    pt          t                    }t          |                     d          d          ||t          |                     d                    t          |                     d                    t          |                     d	                    t!          |                     d
                    t#          |                     d          d          t%          |                     d                    t'          |                     d                    d
S )Nrr   c                0    g | ]}t          |d           S )Trb   )rk   r   items     r   r   z%_normalize_preset.<locals>.<listcomp>I  s%    IIIKd333IIIr   c                    g | ]}||S Nr   r   s     r   r   z%_normalize_preset.<locals>.<listcomp>J  s    666TT%5D%5%5%5r   rs   r   Tr   r   r   r   rh   r   r   r   )
r   rr   rs   r   r   r   r   rh   r   r   )r$   rC   rD   r*   jsonloadsJSONDecodeErrorr!   rw   r   rk   r   r   ra   r"   r)   r2   r6   r:   rJ   )rn   raw_refsr~   rs   s       r   _normalize_presetr   9  s   c4   ww)**H(C   	z(++HH$j1 	 	 	HHH	h%% D ",Hd!;!;CH::IIIIID66T666D +(**SWW\2233Wx@V7W7WJ  	 2 2D99  !6sww?V7W7W!X!X"7@X8Y8Y"Z"Z6sww?R7S7STT%FGG/00&
 &
 "#'',"7"7>> !4CGG<R4S4S T T !!2!233A! ! !s   A A32A3c                   t          | t                    si } |                     d          }i }t          |t                    rQ|                                D ]<\  }}t	          |pd                                          }|rt          |          ||<   =|st          |           |t          <   t	          |                     d          pd                                          }|r||vr"t          t          |          t                    }||vrt                      ||<   t	          |                     d          pd                                          }||vrd}||         }|||t          |d                   t          |d                   |d         |d         |d	         |d
         |d         |                    d          |                    dd          |d         t          |                     d                    dS )zReturn validated MoA config with named presets.

    Backward compatible with the first PR shape where ``moa`` itself contained
    ``reference_models`` and ``aggregator`` directly.
    rq   r   default_presetactive_presetrr   rs   r   r   r   r   rh   r   r   rA   r   privacy_filter)r   r   rq   rr   rs   r   r   r   r   rh   r   r   r   r   )r$   rC   rD   ru   r*   r/   r   rt   nextiterr   r   rR   )	rn   ry   rq   r{   r|   
clean_namedefault_nameactive_nameactives	            r   normalize_moa_configr   t  s    c4   '')$$K)+G+t$$ @'--// 	@ 	@LD&TZR..00J @&7&?&?
#  B+<S+A+A'(sww/006B77==??L D<w66DMM+BCC7"" / 1 1cggo..4"55;;==K'!!\"F&$$V,>%?@@vl344!'(?!@"()A"B#$78%+,G%H\* &

+A B B**X{33)$ 08H0I0IJJ%  r   configc                n    t          |           }t          |d                                                   S )Nrq   )r   rw   keys)r   cfgs     r   list_moa_presetsr     s-    
v
&
&CI##%%&&&r   r{   c                \   t          |           }t          |p|                    d          pt                                                    }|d                             |          }|5ddlm} d                    |d                   pd} |d| d| d	          t          |          S )
Nr   rq   r   )MoAPresetNotFoundErrorz, z(none)zMoA preset 'z$' was not found. Available presets: z. Run `hermes moa list`.)	r   r*   rD   rt   r/   agent.errorsr   joinr   )r   r{   r   preset_namer|   r   	availables          r   resolve_moa_presetr     s    
v
&
&CdRcgg&677R;RSSYY[[K^,,F~777777IIc)n--9	$$3; 3 33 3 3
 
 	
 Fr   r`   c                    t          |pd                                          }|sdS t          |           }|d                             |          }||                    dd          sdS |S )a  Return the preset name iff ``text`` exactly matches an *enabled* preset.

    Used by the no-explicit-provider switch path (PATH B in
    ``hermes_cli/model_switch.py``) to recognize a bare ``/model <preset>``
    that the user typed without the ``moa:`` prefix. This is an *implicit*
    match, so it must honor the per-preset ``enabled`` opt-out: a user who set
    ``enabled: false`` to disable a preset must not have a plain model switch
    whose name happens to collide with that preset key silently pivot the
    session onto the MoA virtual provider (issue #55187). Explicit selection
    via ``--provider moa`` / the model picker does not go through here, so a
    disabled preset is still reachable when the user explicitly asks for it.
    r   Nrq   r   T)r*   r/   r   rD   )r   r`   wantedr   r|   s        r   exact_moa_preset_namer     sq     __""$$F t
v
&
&C^''F~VZZ	488~tMr   c                    t          |           }t          |pd                                          }|r||d         vrt          |          ||d<   |S )Nr   rq   r   )r   r*   r/   KeyError)r   r{   r   ri   s       r   set_active_moa_presetr     s[    
v
&
&C
OO!!##E c)n,,uoo CJr   promptr|   c                    t          | pd          t          |pi |          d}t          j        t	          j        |dd                              d                                        d          }t           | S )zBEncode a /moa one-shot turn for frontends that can only send text.r   )r   r   ),rB   F)
separatorsensure_asciiutf-8ascii)	r*   r   base64urlsafe_b64encoder   dumpsencodedecodeMOA_MARKER_PREFIX)r   r   r|   payloadencodeds        r   encode_moa_turnr     s     fl##$V\r6:: G &
7zFFFMMgVV fWoo   ****r   message!tuple[str, dict[str, Any] | None]c                   t          | t                    r|                     t                    s| dfS | t	          t                    d                                         }	 t          j        t          j	        |
                    d                                        d                    }n# t          $ r | dfcY S w xY wt          |                    d          pd          }|t          |                    d          pi           fS )z%Decode a hidden /moa one-shot marker.Nr   r   r   r   r   )r$   r*   rE   r   lenr/   r   r   r   urlsafe_b64decoder   r   	ExceptionrD   r   )r   r   r   r   s       r   decode_moa_turnr     s   gs## 7+=+=>O+P+P }c+,,--.4466G*V5gnnW6M6MNNUUV]^^__   }X&&,"--F$W[[%:%:%@bAAAAs   #AB0 0C Cuser_promptc                &    t          | ||          S )z>Build the hidden one-shot payload used by TUI/gateway routing.)r|   )r   )r   r   r|   s      r   build_moa_turn_promptr     s    ;v>>>>r   c                     dS )NzUsage: /moa <prompt>  (runs one prompt through the default MoA preset, then restores your model; pick a preset from the model picker to switch for the session)r   r   r   r   	moa_usager     s     m  mr   )r   r   )r   r   r   r   )r   r   r   r*   )r   r   r   r3   r   r3   )r   r   r   r7   )r   r   r   rS   )T)r   r   r   r%   r   r%   )r   r   rc   r%   r   rd   )r   r   r   rS   )rn   r   r   ro   )r   r   )rn   r   r   r   )r   r   r   ro   r   )r   r   r{   rS   r   r   )r   r   r`   r*   r   rS   )NN)r   r*   r   r   r|   rS   r   r*   )r   r   r   r   )r   r*   r   r   r|   rS   r   r*   )r   r*   )(__doc__
__future__r   r   r   r&   copyr   typingr   r   rt   r   __annotations__r   r   r   r"   r)   r2   r6   r:   rJ   rR   rZ   ra   rk   rm   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>r      s   @ @ @ " " " " " "               , #   )44(BCC6      (* *     
 /3  2 2 2 2Z Z Z Z       *> > > >	 	 	 	       $       F   4            7<      >   ,. . . .b   "8 8 8 8v3 3 3 3l' ' ' '
       .   	+ 	+ 	+ 	+ 	+
B 
B 
B 
B? ? ? ? ?
m m m m m mr   