Ë
    ãß²j—   ã                  óö   — d Z ddlmZ ddlZddlZddlmZmZmZm	Z	  ej                  dej                  «      Z ej                  d«      ZdZdd„Zdd	„Z	 	 	 	 	 	 dd
„Z	 	 	 	 	 	 dd„ZdZdd„Z	 	 	 	 	 	 dd„Zy)zldelegate_task input validation: tasks=[...] / legacy goal normalisation, per-task output schemas and images.é    )ÚannotationsN)ÚAnyÚDictÚListÚOptionalz^(todo|task\s*\d+)$z[<[A-Za-z][A-Za-z0-9]*(?:[ _-][A-Za-z0-9]+)+>|\{[A-Za-z][A-Za-z0-9]*(?:[ _-][A-Za-z0-9]+)+\}é
   c                ó8  — t        | t        «      sy| j                  «       }|sy	 t        j                  |«      }t        |t        «      sddt        |«      j                  › d�fS |dfS # t        j
                  $ r}dd|j                  › d�fcY d}~S d}~ww xY w)zp``(parsed_list, None)`` for a JSON-array string, ``(None, error)`` for a bad string, ``(None, None)`` otherwise.©NN)Nz7Provide either 'goal' (single task) or 'tasks' (batch).Nz`tasks must be a JSON array of task objects; received a string that could not be parsed as JSON (z).z3tasks must be a JSON array of task objects; parsed z	 instead.)
Ú
isinstanceÚstrÚstripÚjsonÚloadsÚJSONDecodeErrorÚmsgÚlistÚtypeÚ__name__)ÚtasksÚrawÚparsedÚexcs       ú>/home/ubuntu/.hermes/hermes-agent/tools/delegate_tool_tasks.pyÚ_recover_tasks_from_json_stringr      s´   € ä�eœSÔ!ØØ
�+‰+‹-€CÙØNðDÜ—‘˜C“ˆô �fœdÔ#ØÐJÌ4ÐPVË<×K`ÑK`ÐJaÐajÐkÐkÐkØ�4ˆ<Ðøô	 ×Ñò DØÐwÐx{×xÑxð  xAð  ACð  Dð  Dõ  	DûðDús   ¦A* Á*BÁ=BÂBÂBc                óÚ  — t        | «      D ]Ý  \  }}t        |j                  dd«      «      j                  «       }t        j                  dj                  |j                  «       j                  «       «      «      rd|› d|›d�c S t        j                  |«      }|rd|› d|j                  d«      ›d	�c S t        |«      t        k  sŒ¾t        | «      d
k\  sŒÍd|› d|›dt        › d�c S  y)u:  Batch-only quality gate beyond per-task goal presence; actionable error or None. No minimum count: a one-entry
    array is the canonical single-task shape (legacy top-level `goal` is wrapped into one). Duplicate goals are
    deliberately NOT rejected â€” identical-goal fan-outs (best-of-N / ensemble sampling) are legitimate and blocking
    them broke real workflows. The too-short check applies only to multi-task fan-outs (terse goals there are
    usually unexpanded templates); a SINGLE task legitimately uses short goals ("Fix the tests").

    See #81141.
    ÚgoalÚ Ú úTask z has a placeholder goal (za). Replace it with a specific, self-contained description of what the subagent should accomplish.z. goal contains an unexpanded template marker (r   ud   ). Substitute the real value before calling delegate_task â€” subagents cannot resolve placeholders.é   z goal is too short (z5). Write a specific, self-contained goal of at least z5 characters so the subagent knows exactly what to do.N)Ú	enumerater   Úgetr   Ú_PLACEHOLDER_GOAL_REÚmatchÚjoinÚlowerÚsplitÚ_TEMPLATE_MARKER_REÚsearchÚgroupÚlenÚ_MIN_BATCH_GOAL_LEN)Ú	task_listÚiÚtaskr   Úmarkers        r   Ú_validate_batch_tasksr1   $   s  € ô ˜YÓ'ò ‰ˆˆ4Ü�4—8‘8˜F BÓ'Ó(×.Ñ.Ó0ˆÜ×%Ñ% c§h¡h¨t¯z©z«|×/AÑ/AÓ/CÓ&DÔEà˜�sÐ3°D°8ð <fð fòô %×+Ñ+¨DÓ1ˆÙà˜�sð Ø—L‘L “OÐ&ð 'SðSòô
 ˆt‹9Ô*Ó*¬s°9«~ÀÓ/Bà˜�sÐ.¨t¨hð 73Ü3FÐ2Gð H&ð&òðð( ó    c                óZ  — t        |«      \  }}|rd|fS |�|}t        |t        «      r|sd}|r5t        |t        «      r%t        |«      |kD  rddt        |«      › d|› d�fS |}n5| r2t        | t        «      r"| j                  «       r| ||dœg}|�
||d   d<   nyt        |«      D ]_  \  }	}
t        |
t        «      s dd	|	› d
t        |
«      j                  › d�fc S |
j                  dd«      j                  «       rŒWdd	|	› d�fc S  t        |t        «      rt        |«      nd}|rd|fS |dfS )za``(task_list, None)`` from ``tasks=[...]`` or the legacy single ``goal``, else ``(None, error)``.NzToo many tasks: z* provided, but max_concurrent_children is z‡. Either reduce the task count, split into multiple delegate_task calls, or increase delegation.max_concurrent_children in config.yaml.)r   ÚcontextÚroler   Úoutput_schema)Nuƒ   No tasks provided. Pass tasks=[{goal: '...', context: '...'}, ...] â€” one entry per subagent (a single task is a one-entry array).r   z must be an object, got ú.r   r   z is missing a 'goal'.)r   r   r   r+   r   r   r!   Údictr   r   r"   r1   )r   r4   r   r6   Útop_roleÚmax_childrenÚrecovered_tasksÚtasks_errorr-   r.   r/   Úbatch_errors               r   Ú_normalize_task_listr>   C   so  € ô $CÀ5Ó#IÑ €O�[ÙØ�[Ð Ð ØÐ"Øˆä�%œÔ¡uØˆá”˜E¤4Ô(Üˆu‹:˜Ò$ØØ"¤3 u£: ,Ð.XÐYeÐXfð gEð Fðð ð
 ‰	Ù	”*˜T¤3Ô'¨D¯J©J¬LØ"¨wÀÑIÐJˆ	ØÐ$Ø,9ˆI�a‰L˜Ò)ð
ô
 ˜YÓ'ò :‰ˆˆ4Ü˜$¤Ô%Ø˜5  Ð#;¼DÀ»J×<OÑ<OÐ;PÐPQÐRÐRÒRØ�x‰x˜ Ó#×)Ñ)Õ+Ø˜5  Ð#8Ð9Ð9Ò9ð	:ô 7AÀÌÔ6MÔ'¨	Ô2ÐSW€KÙ"-ˆD�+ÐÐD°I¸tÐ3DÐDr2   c                óÞ   — ddl m} g }t        | «      D ]T  \  }}|j                  d«      }|€t	        | «      dk(  r|�|} ||«      \  }}|rg d|› d|› �fc S |j                  |«       ŒV |dfS )zµPer-task coerced output schemas. A malformed output_schema fails the whole call before any child spawns;
    schema-less tasks resolve to None and take no new code paths downstream.r   )Úcoerce_output_schemar6   Né   r   z output_schema invalid: )Útools.delegation_output_schemar@   r!   r"   r+   Úappend)	r-   r6   r@   Útask_schemasr.   r/   Ú
raw_schemaÚcoerced_schemaÚ
schema_errs	            r   Ú_coerce_task_schemasrH   k   s”   € õ
 DØ35€LÜ˜YÓ'ò ,‰ˆˆ4Ø—X‘X˜oÓ.ˆ
ØÐ¤# i£.°AÒ"5¸-Ð:SØ&ˆJÙ%9¸*Ó%EÑ"ˆ˜
ÙØ˜˜q˜cÐ!9¸*¸ÐFÐFÒFØ×Ñ˜NÕ+ð,ð ˜ÐÐr2   é   c                óŽ  — | j                  d«      }|€yt        |t        «      r|g}t        |t        «      sdd|› d�fS g }|D ]K  }t        |t        «      r|j	                  «       s
dd|› d�fc S |j                  |j	                  «       «       ŒM t        |«      t        kD  rdd|› dt        |«      › dt        › d	�fS |xs ddfS )
zÚ``(cleaned_list_or_None, None)`` for a task's optional ``images`` (local paths, http(s) or data: URLs), else
    ``(None, error)``. A bare string is wrapped into a one-entry list (small models emit scalars for arrays).ÚimagesNr
   r   z? 'images' must be an array of local file paths or http(s) URLs.zO 'images' entries must be non-empty strings (local file paths or http(s) URLs).z has z images; the per-task limit is z5. Trim to the images the child actually needs to see.)r"   r   r   r   r   rC   r+   Ú_MAX_TASK_IMAGES)r/   r.   r   ÚcleanedÚitems        r   Ú_normalize_task_imagesrO      së   € ð �(‰(�8Ó
€CØ
€{ØÜ�#”sÔØˆeˆÜ�cœ4Ô Ø�u˜Q˜CÐ^Ð_Ð_Ð_Ø€GØò %ˆÜ˜$¤Ô$¨D¯J©J¬LØ˜5  Ð#rÐsÐsÒsØ�‰�t—z‘z“|Õ$ð%ô ˆ7ƒ|Ô&Ò&ØØ�A�3�eœC ›L˜>Ð)HÔIYÐHZð [Bð Bð
ð 	
ð ŠO�t˜dÐ"Ð"r2   c                óÖ   — g }t        | «      D ]V  \  }}|j                  d«      €t        | «      dk(  r
|�i |¥d|i¥}t        ||«      \  }}|rg |fc S |j	                  |«       ŒX |dfS )z¹Per-task validated image lists; a malformed list fails the whole call before any child spawns. The legacy
    top-level ``images`` applies to a single task only, like ``output_schema``.rK   NrA   )r!   r"   r+   rO   rC   )r-   rK   Útask_imagesr.   r/   rM   Úerrs          r   Ú_coerce_task_imagesrS   •   sˆ   € ð
 .0€KÜ˜YÓ'ò $‰ˆˆ4Ø�8‰8�HÓÐ%¬#¨i«.¸AÒ*=À&ÐBTØ-�dÐ-˜H fÑ-ˆDÜ-¨d°AÓ6‰ˆ�ÙØ�s�7ŠNØ×Ñ˜7Õ#ð$ð ˜ÐÐr2   )r   r   Úreturnú4tuple[Optional[List[Dict[str, Any]]], Optional[str]])r-   úList[Dict[str, Any]]rT   zOptional[str])r9   r   r:   ÚintrT   rU   )r-   rV   r6   zOptional[Dict[str, Any]]rT   z4tuple[List[Optional[Dict[str, Any]]], Optional[str]])r/   r8   r.   rW   rT   z)tuple[Optional[List[str]], Optional[str]])r-   rV   rK   zOptional[List[str]]rT   z/tuple[List[Optional[List[str]]], Optional[str]])Ú__doc__Ú
__future__r   r   ÚreÚtypingr   r   r   r   ÚcompileÚ
IGNORECASEr#   r(   r,   r   r1   r>   rH   rL   rO   rS   © r2   r   ú<module>r_      sÀ   ðÙ rå "ã Û 	ß ,Ó ,ð "�r—z‘zÐ"8¸"¿-¹-ÓHÐ Ø �b—j‘jØbóÐ ð Ð óóð>&EØ36ð&EØFIð&Eà9ó&EðPØ#ðØ4Lðà9óð$ Ð ó#ð,Ø#ðØ-@ðà4ôr2   