
     Yj:                       U d Z ddlm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:dZd;dZd<dZd=dZd>dZd?d!Zd@d"ZdAd%ZdBd'ZdCd(ZdCd)ZdDd+ZdEdFd-ZdGd/ZdFd0ZdHdId3ZdJd6ZdHdKd8ZdLd9Z dS )Mz: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valuer   returnfloat | Nonec                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    JC:\Users\server\AppData\Local\hermes\hermes-agent\hermes_cli\moa_config.py_coerce_float_or_noner      sN     }tU||z"   tts    00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   r   r   r   r   )r   r   s     r   _coerce_intr   (   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   r   )r   ns     r   _coerce_int_or_noner   4   s     }tJJz"   	E%LL!!AA:& 	 	 	444	 A
 A114s2    A'A
A'A!A' A!!A'&A'strc                |    t          | pd                                                                          }|dv r|ndS )zCNormalize the fan-out cadence; unknown values fall back to default.r   >   	user_turnper_iterationr#   )r    striplower)r   modes     r   _coerce_fanoutr'   F   s@    u{!!##))++D99944N    
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_effortNTenabledFnoneeffort)hermes_constantsr+   get)r   r+   parseds      r   _clean_reasoning_effortr2   L   sn    777777}t##E**F~tzz)%%v::hr(   slotdict[str, Any] | Nonec                   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<   |S )Nr	   r   r
   moar   reasoning_effort)
isinstancedictr    r0   r$   r%   r2   )r3   r	   r
   cleanr.   s        r   _clean_slotr;   Z   s    dD!! t488J''-2..4466H!!'R((..00E 5 t ~~5  t)1EBBE$TXX.@%A%ABBF +$* !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)r6   zMthe Mixture of Agents provider cannot be used inside a preset (recursive MoA)N)r8   r9   r    r0   r$   r%   )r3   r	   r
   s      r   _slot_problemr=   o   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    z: z.': needs at least one complete reference model
aggregatorz' aggregator: )r8   r9   r0   DEFAULT_MOA_PRESET_NAMEitemsr    r$   appendlist	enumerater=   )r>   presets_rawrA   problemsnamepresetlabelrefscomplete_refsindexr3   issue	agg_issues                r   validate_moa_payloadrT      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            	     `    t          t                    t          t                    d d dd dddS )N   r#   T)rB   rD   reference_temperatureaggregator_temperature
max_tokensreference_max_tokensfanoutr,   )r   r   r    r(   r   _default_presetr^      s=    $%ABB566 "&"& $!  r(   c                   t          | t                    si } |                     d          }t          |t                    st          |t                    r|gng }d |D             }d |D             }|st	          t
                    }t          |                     d                    pt	          t                    }t          |                     dd                    ||t          |                     d                    t          |                     d                    t          |                     d	          d
          t          |                     d                    t          |                     d                    dS )NrB   c                ,    g | ]}t          |          S r]   )r;   .0items     r   
<listcomp>z%_normalize_preset.<locals>.<listcomp>   s     333$K333r(   c                    g | ]}||S Nr]   ra   s     r   rd   z%_normalize_preset.<locals>.<listcomp>   s    666TT%5D%5%5%5r(   rD   r,   TrX   rY   rZ   rW   r[   r\   )r,   rB   rD   rX   rY   rZ   r[   r\   )r8   r9   r0   rH   r   r   r;   r   boolr   r   r   r'   )r>   raw_refsrO   rD   s       r   _normalize_presetri      si   c4   ww)**Hh%% D ",Hd!;!;CH::33(333D66T666D 6455SWW\2233Wx@V7W7WJ 	40011  !6sww?V7W7W!X!X"7@X8Y8Y"Z"Z!#'',"7"7>> !4CGG<R4S4S T T !!2!233-  r(   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S )zReturn validated MoA config with named presets.

    Backward compatible with the first PR shape where ``moa`` itself contained
    ``reference_models`` and ``aggregator`` directly.
    rA   r   default_presetactive_presetrB   rD   rX   rY   rZ   r[   r\   r#   r,   )rk   rl   rA   rB   rD   rX   rY   rZ   r[   r\   r,   )r8   r9   r0   rF   r    r$   ri   rE   nextiterr^   r   )	r>   rJ   rA   rL   rM   
clean_namedefault_nameactive_nameactives	            r   normalize_moa_configrs      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\* &

+A B B**X77)$  r(   configc                n    t          |           }t          |d                                                   S )NrA   )rs   rH   keys)rt   cfgs     r   list_moa_presetsrx      s-    
v
&
&CI##%%&&&r(   rL   c                   t          |           }t          |p|                    d          pt                                                    }|d                             |          }|t          |          t          |          S )Nrk   rA   )rs   r    r0   rE   r$   KeyErrorr   )rt   rL   rw   preset_namerM   s        r   resolve_moa_presetr|   %  sx    
v
&
&CdRcgg&677R;RSSYY[[K^,,F~{###Fr(   textc                    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   NrA   r,   T)r    r$   rs   r0   )rt   r}   wantedrw   rM   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   rA   rl   )rs   r    r$   rz   )rt   rL   rw   r:   s       r   set_active_moa_presetr   E  s[    
v
&
&C
OO!!##E c)n,,uoo CJr(   promptrM   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   rt   ),:F)
separatorsensure_asciiutf-8ascii)	r    r|   base64urlsafe_b64encodejsondumpsencodedecodeMOA_MARKER_PREFIX)r   rt   rM   payloadencodeds        r   encode_moa_turnr   N  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   rt   )r8   r    
startswithr   lenr$   r   loadsr   urlsafe_b64decoder   r   	Exceptionr0   ri   )r   r   r   r   s       r   decode_moa_turnr   Z  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.)rM   )r   )r   rt   rM   s      r   build_moa_turn_promptr   g  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   l  s     m  mr(   )r   r   r   r   )r   r   r   r   r   r   )r   r   r   r   )r   r   r   r    )r   r   r   r)   )r3   r   r   r4   )r3   r   r   r)   )r>   r   r   r?   )r   rU   )r>   r   r   rU   )rt   r   r   r?   rf   )rt   r   rL   r)   r   rU   )rt   r   r}   r    r   r)   )NN)r   r    rt   r   rM   r)   r   r    )r   r   r   r   )r   r    rt   r   rM   r)   r   r    )r   r    )!__doc__
__future__r   r   r   copyr   typingr   r   rE   r   __annotations__r   r   r   r   r'   r2   r;   r=   rT   r^   ri   rs   rx   r|   r   r   r   r   r   r   r]   r(   r   <module>r      sf   @ @ @ " " " " " "              , #   )44(BCC6      (* *         	 	 	 	       $O O O O          *   ,. . . .b   ( ( ( (V- - - -`' ' ' '
       .   	+ 	+ 	+ 	+ 	+
B 
B 
B 
B? ? ? ? ?
m m m m m mr(   