
    `gj9                       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d,dZd-dZd.dZd.dZd/dZd0d1dZd2dZd1d Zd3d4d!Zd5d"Zd3d6d#Zd7d$Z y)8z: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_AGGREGATORc                T    | | dk(  ry	 t        |       S # t        t        f$ r Y y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)values    H/root/.hermes/venv/lib/python3.12/site-packages/hermes_cli/moa_config.py_coerce_float_or_noner      s8     }U|z" s   
 ''c                    | | dk(  r|S 	 t        |       S # t        t        f$ r1 	 t        t        |             cY S # t        t        f$ r |cY cY S w xY ww xY w)Nr   intr   r   r   )r   r   s     r   _coerce_intr   (   sb    }5zz" 	uU|$$:& 	N	s)   
 A<AAAAAc                    | | dk(  ry	 t        |       }|dkD  r|S dS # t        t        f$ r/ 	 t        t        |             }n# t        t        f$ r Y Y yw xY wY Fw xY w)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   sx     }J A14 z" 	E%L!A:& 		 s2    AAAAAAAAc                h    t        | xs d      j                         j                         }|dv r|S dS )zCNormalize the fan-out cadence; unknown values fall back to default.r   >   	user_turnper_iterationr   )strstriplower)r   modes     r   _coerce_fanoutr$   F   s5    u{!!#))+D994NN    c                |    ddl m} | | du ry ||       }|y|j                  d      du ry|j                  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_effortr.   L   sH    7}#E*F~zz)%::hr%   c                V   t        | t              sy t        | j                  d      xs d      j	                         }t        | j                  d      xs d      j	                         }|r|sy |j                         dk(  ry ||d}t        | j                  d            }|r||d<   |S )Nr	   r   r
   moar   reasoning_effort)
isinstancedictr    r,   r!   r"   r.   )slotr	   r
   cleanr*   s        r   _clean_slotr6   Z   s    dD!488J'-2.446H!'R(..0E5 ~~5 )1EBE$TXX.@%ABF$* !Lr%   c                   t        | t              syt        | j                  d      xs d      j	                         }t        | j                  d      xs d      j	                         }|s|sy|sy|sd| dS |j                         d	k(  ry
y)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)r0   zMthe Mixture of Agents provider cannot be used inside a preset (recursive MoA)N)r2   r3   r    r,   r!   r"   )r4   r	   r
   s      r   _slot_problemr8   o   s     dD!>488J'-2.446H!'R(..0EE0%.xj8PQQ~~5 ^r%   c           
        t        | t              sdgS | j                  d      }t        |t              r|r|}nt        | i}g }|j	                         D ]  \  }}t        |xs d      j                         xs d}t        |t              s|j                  d| d       N|j                  d      }t        |t              st        |t              r|gng }d}t        |      D ]5  \  }	}
t        |
      }|r|j                  d| d	|	d
z    d|        1|d
z  }7 |s|j                  d| d       t        |j                  d            }|s|j                  d| d|         |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: )r2   r3   r,   DEFAULT_MOA_PRESET_NAMEitemsr    r!   appendlist	enumerater8   )rawpresets_rawr:   problemsnamepresetlabelrefscomplete_refsindexr4   issue	agg_issues                r   validate_moa_payloadrN      sr    c4 .//'')$K+t$"- +C0H IfDJB%%'6;&$'OOhug-ABCzz,-$%'d3D6D$T? 	#KE4!$'E(5'eai[5' RS"	# OOhug-[\]!&**\":;	OOhug^I;GH+I. Or%   c            	     L    t        t              t        t              d d dd dddS )N   r   T)r;   r=   reference_temperatureaggregator_temperature
max_tokensreference_max_tokensfanoutr(   )r   r   r    r%   r   _default_presetrW      s2    $%AB56 "&"& $! r%   c                   t        | t              si } | j                  d      }t        |t              st        |t              r|gng }|D cg c]  }t	        |       }}|D cg c]  }||	 }}|st        t              }t	        | j                  d            xs t        t              }t        | j                  dd            ||t        | j                  d            t        | j                  d            t        | j                  d      d      t        | j                  d	            t        | j                  d
            dS c c}w c c}w )Nr;   r=   r(   TrQ   rR   rS   rP   rT   rU   )r(   r;   r=   rQ   rR   rS   rT   rU   )r2   r3   r,   rA   r6   r   r   r   boolr   r   r   r$   )rC   raw_refsitemrI   r=   s        r   _normalize_presetr\      s%   c4 ww)*Hh% ",Hd!;H:*23$K3D3!6TT%5D6D645SWW\23Wx@V7WJ 	401  !6sww?V7W!X"7@X8Y"Z!#'',"7> !4CGG<R4S T !!23-  46s   E%E-Ec                   t        | t              si } | j                  d      }i }t        |t              rF|j                         D ]3  \  }}t	        |xs d      j                         }|s&t        |      ||<   5 |st        |       |t        <   t	        | j                  d      xs d      j                         }|r||vrt        t        |      t              }||vrt               ||<   t	        | j                  d      xs d      j                         }||vrd}||   }|||t        |d         t        |d         |d   |d   |d	   |j                  d
      |j                  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.
    r:   r   default_presetactive_presetr;   r=   rQ   rR   rS   rT   rU   r   r(   )r^   r_   r:   r;   r=   rQ   rR   rS   rT   rU   r(   )r2   r3   r,   r?   r    r!   r\   r>   nextiterrW   r   )	rC   rD   r:   rF   rG   
clean_namedefault_nameactive_nameactives	            r   normalize_moa_configrf      s    c4 '')$K)+G+t$'--/ 	@LD&TZR..0J&7&?
#	@ +<S+A'(sww/06B7==?L<w6DM+BC7" / 1cggo.4"5;;=K'!\"F&$$V,>%?@vl34!'(?!@"()A"B\* &

+A B**X7)$ r%   c                P    t        |       }t        |d   j                               S )Nr:   )rf   rA   keys)configcfgs     r   list_moa_presetsrk      s$    
v
&CI##%&&r%   c                   t        |       }t        |xs |j                  d      xs t              j	                         }|d   j                  |      }|-ddlm} dj                  |d         xs d} |d| d| d	      t        |      S )
Nr^   r:   r   )MoAPresetNotFoundErrorz, z(none)zMoA preset 'z$' was not found. Available presets: z. Run `hermes moa list`.)	rf   r    r,   r>   r!   agent.errorsrm   joinr   )ri   rF   rj   preset_namerG   rm   	availables          r   resolve_moa_presetrr   %  s    
v
&CdRcgg&67R;RSYY[K^,F~7IIc)n-9	$;-'Kk13
 	
 Fr%   c                    t        |xs d      j                         }|syt        |       }|d   j                  |      }||j                  dd      sy|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   Nr:   r(   T)r    r!   rf   r,   )ri   textwantedrj   rG   s        r   exact_moa_preset_namerv   4  sX     _""$F
v
&C^'F~VZZ	48Mr%   c                    t        |       }t        |xs d      j                         }|r||d   vrt        |      ||d<   |S )Nr   r:   r_   )rf   r    r!   KeyError)ri   rF   rj   r5   s       r   set_active_moa_presetry   K  sI    
v
&C
O!!#Ec)n,uo CJr%   c                    t        | xs d      t        |xs i |      d}t        j                  t	        j
                  |dd      j                  d            j                  d      }t         | S )zBEncode a /moa one-shot turn for frontends that can only send text.r   )promptri   ),:F)
separatorsensure_asciiutf-8ascii)	r    rr   base64urlsafe_b64encodejsondumpsencodedecodeMOA_MARKER_PREFIX)r{   ri   rG   payloadencodeds        r   encode_moa_turnr   T  sp     fl#$V\r6:G &&

7zFMMgVfWo    	**r%   c                   t        | t              r| j                  t              s| dfS | t	        t              d j                         }	 t        j                  t        j                  |j                  d            j                  d            }t        |j                  d      xs d      }|t        |j                  d      xs i       fS # t        $ r | dfcY S w xY w)z%Decode a hidden /moa one-shot marker.Nr   r   r{   r   ri   )r2   r    
startswithr   lenr!   r   loadsr   urlsafe_b64decoder   r   	Exceptionr,   r\   )messager   r   r{   s       r   decode_moa_turnr   `  s    gs#7+=+=>O+P}c+,-.446G**V55gnnW6MNUUV]^_ X&,"-F$W[[%:%@bAAA  }s   AC CCc                    t        | ||      S )z>Build the hidden one-shot payload used by TUI/gateway routing.)rG   )r   )user_promptri   rG   s      r   build_moa_turn_promptr   m  s    ;v>>r%   c                      y)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)rV   rV   r%   r   	moa_usager   r  s     mr%   )r   r   returnzfloat | None)r   r   r   r   r   r   )r   r   r   z
int | None)r   r   r   r    )r   r   r   
str | None)r4   r   r   zdict[str, Any] | None)r4   r   r   r   )rC   r   r   	list[str])r   dict[str, Any])rC   r   r   r   )ri   r   r   r   )N)ri   r   rF   r   r   r   )ri   r   rt   r    r   r   )NN)r{   r    ri   r   rG   r   r   r    )r   r   r   z!tuple[str, dict[str, Any] | None])r   r    ri   r   rG   r   r   r    )r   r    )!__doc__
__future__r   r   r   copyr   typingr   r   r>   r   __annotations__r   r   r   r   r$   r.   r6   r8   rN   rW   r\   rf   rk   rr   rv   ry   r   r   r   r   rV   r%   r   <module>r      s    @ "    , #   )4(BC6 2  (*   	 $O *,.b(V-`'
.	+
B?
mr%   