§
    øžyjŠó  ã                  óp  — U d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	m
Z
 ddlmZ ddlmZmZmZmZmZmZ ddlmZ ddlmZ dd	lmZ  ej        e¦  «        ZeZdad
ed<    ej         ¦   «         Z!da"ded<    ej         ¦   «         Z#i Z$ded<   dZ%dZ&dZ'dZ(dZ) ej         ¦   «         Z*dZ+dZ,dZ-dZ. ej         ¦   «         Z/da0ded<    ej1        ¦   «         Z2d„ Z3dd„Z4d€d!„Z5ed�d#„¦   «         Z6d‚d&„Z7dƒd)„Z8d„d*„Z9d…d-„Z:dƒd.„Z;d†d/„Z<d†d0„Z=d‡d2„Z>dˆd4„Z?d‰d8„Z@dˆd9„ZAdˆd:„ZBdˆd;„ZCdŠd<„ZDdŠd=„ZEd‹d?„ZFdŒdB„ZGd†dC„ZHd�dE„ZId†dF„ZJdGdGdGdHœdŽdK„ZK	 	 	 d�d�dL„ZLd‘dM„ZMd„dN„ZNd‘dO„ZOddGdGde%ddPœd’d_„ZPd“da„ZQd”dc„ZRd•dd„ZSd–de„ZTddGdGde%dddfœd—di„ZUd˜dk„ZVd™dm„ZWd„dn„ZXd„do„ZYdƒdp„ZZdšdv„Z[d›dx„Z\dœd�d{„Z]	 	 	 	 dždŸd}„Z^d„d~„Z_dS ) u  
Async (background) delegation registry.

Backs ``delegate_task(background=true)``: the parent agent dispatches a
subagent that runs on a module-level daemon executor and returns a handle
immediately, so the user and the model can keep working while the child runs.

When the child finishes, a completion event is pushed onto the SHARED
``process_registry.completion_queue`` with ``type="async_delegation"``. The
CLI (``cli.py`` process_loop) and gateway (``_run_process_watcher`` /
``completion_queue`` drain) already poll that queue while the agent is idle
and forge a fresh user/internal turn from each event. We deliberately reuse
that rail rather than reaching into a running agent loop:

  - completions surface as a NEW turn when the agent is idle, never spliced
    between a tool result and an assistant message. That keeps strict
    message-role alternation legal and the prompt cache intact (hard
    invariant: never mutate past context).
  - we inherit the queue's de-dup, crash-recovery checkpoint, and the
    existing CLI + gateway drain wiring for free â€” no new drain loops in the
    two largest files in the repo.

The completion payload carries a RICH, self-contained task-source block (the
original goal, the context the parent supplied, toolsets, model, dispatch
time, status, and the full result summary). When the result re-enters the
conversation the parent may be deep in unrelated context and won't remember
why the subagent existed; the block lets it either use the result or
re-dispatch if the world has moved on.

This module owns ONLY the async lifecycle. The actual child build + run is
delegated back to ``delegate_tool._run_single_child`` via an injected
runner, so all the credential leasing, heartbeat, timeout, and result-shaping
logic stays in one place.
é    )ÚannotationsN)ÚThreadPoolExecutor)Úcontextmanager)ÚAnyÚCallableÚDictÚIteratorÚListÚOptional©Úget_hermes_home)ÚDaemonThreadPoolExecutor)Úpropagate_context_to_threadzOptional[ThreadPoolExecutor]Ú	_executorÚintÚ_executor_max_workerszDict[str, Dict[str, Any]]Ú_recordsé   é2   i€:	 iè  é   g      >@g      |@g     À’@g      ^@zOptional[threading.Thread]Ú_monitor_threadc                 ó$   — t          ¦   «         dz  S )Nzstate.dbr   © ó    ú</home/ragecks/.hermes/hermes-agent/tools/async_delegation.pyÚ_db_pathr   w   s   € ÝÑÔ˜zÑ)Ð)r   Úreturnúsqlite3.Connectionc                 óî   — t          ¦   «         } | j                             dd¬¦  «         t          j        | d¬¦  «        }	 t          |¦  «         n## t          $ r |                     ¦   «          ‚ w xY w|S )NT)ÚparentsÚexist_oké
   ©Útimeout)r   ÚparentÚmkdirÚsqlite3ÚconnectÚ_initialize_schemaÚ	ExceptionÚclose)ÚpathÚconns     r   Ú_connectr.   {   s„   € Ý‰:Œ:€DØ„K×Ò˜d¨TÐÑ2Ô2Ð2ÝŒ?˜4¨Ð,Ñ,Ô,€DðÝ˜4Ñ Ô Ð Ð øÝð ð ð ð 	�
Š
‰ŒˆØð	øøøð
 €Ks   ÁA Á A2r-   ÚNonec                óâ   — ddl m}  || d¬¦  «         |                      d¦  «         d„ |                      d¦  «        D ¦   «         }dD ]$\  }}||vr|                      d	|› d
|› �¦  «         Œ%d S )Nr   )Úapply_wal_with_fallbackzstate.db (async_delegation))Údb_labela+  CREATE TABLE IF NOT EXISTS async_delegations (
            delegation_id TEXT PRIMARY KEY,
            origin_session TEXT NOT NULL,
            origin_ui_session_id TEXT NOT NULL DEFAULT '',
            parent_session_id TEXT,
            state TEXT NOT NULL,
            dispatched_at REAL NOT NULL,
            completed_at REAL,
            updated_at REAL NOT NULL,
            event_json TEXT,
            result_json TEXT,
            delivery_state TEXT NOT NULL DEFAULT 'pending',
            delivery_attempts INTEGER NOT NULL DEFAULT 0,
            delivered_at REAL,
            owner_pid INTEGER,
            owner_started_at INTEGER,
            task_json TEXT,
            delivery_claim TEXT,
            delivery_claimed_at REAL,
            origin_session_id TEXT NOT NULL DEFAULT ''
        )c                ó   — h | ]
}|d          ’ŒS )é   r   )Ú.0Úrows     r   ú	<setcomp>z%_initialize_schema.<locals>.<setcomp>¤   s   € ÐVÐVÐV˜#ˆs�1ŒvÐVÐVÐVr   z$PRAGMA table_info(async_delegations)))Ú	owner_pidÚINTEGER)Úowner_started_atr9   )Ú	task_jsonÚTEXT)Údelivery_claimr<   )Údelivery_claimed_atÚREAL)Úorigin_session_idr<   z)ALTER TABLE async_delegations ADD COLUMN Ú )Úhermes_stater1   Úexecute)r-   r1   ÚcolumnsÚnameÚsql_types        r   r)   r)   ‰   s½   € Ø4Ð4Ð4Ð4Ð4Ð4àÐ˜DÐ+HÐIÑIÔIÐIØ‡L‚Lð	ñô ð ð. WÐV §¢Ð.TÑ!UÔ!UÐVÑVÔV€Gðð Xð X‰ˆˆhð �wÐÐØ�LŠLÐVÀTÐVÐVÈHÐVÐVÑWÔWÐWøðXð Xr   úIterator[sqlite3.Connection]c               #  ó¾   K  — t          ¦   «         } 	 | 5  | V — ddd¦  «         n# 1 swxY w Y   |                      ¦   «          dS # |                      ¦   «          w xY w)u  Open a connection, commit/rollback on exit, and ALWAYS close it.

    ``sqlite3.Connection.__enter__``/``__exit__`` only commit or roll back the
    transaction; they do not close the connection. Using ``with _connect()``
    alone therefore leaks a connection â€” and its WAL/SHM file descriptors â€” on
    every durable dispatch, completion, and delivery-claim, deferring the close
    to the garbage collector. On a long-running gateway that exhausts
    ``RLIMIT_NOFILE`` (the cron-ledger sibling of this bug was #69567 / PR #69594).
    N)r.   r+   )r-   s    r   Ú_transactionrI   µ   sŸ   è è € õ ‰:Œ:€DðØð 	ð 	ØˆJˆJˆJð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	ð 	�
Š
‰Œˆˆˆøˆ�
Š
‰Œˆˆøøøs&   ’A ”%™A ¥)©A ¬)­A ÁAÚrecordúDict[str, Any]c                óÐ  ‡ — t          j         ¦   «         }	 ddlm}  |t          d¦  «                             ¦   «         ¦  «        }n# t
          $ r d }Y nw xY wˆ fd„dD ¦   «         }t          5  t          ¦   «         5 }|                     d‰ d         ‰  	                    dd	¦  «        ‰  	                    d
d	¦  «        ‰  	                    d¦  «        ‰ d         |t          d¦  «                             ¦   «         |t          j        |¦  «        ‰  	                    dd	¦  «        f
¦  «         d d d ¦  «         n# 1 swxY w Y   d d d ¦  «         n# 1 swxY w Y   t          ¦   «          d S )Nr   )Úget_process_start_timeÚosc                óD   •— i | ]}|‰v ¯|‰                      |¦  «        “ŒS r   ©Úget)r5   ÚkeyrJ   s     €r   ú
<dictcomp>z%_persist_dispatch.<locals>.<dictcomp>Ï   s6   ø€ ð ð ð àØ�&ˆ=ˆ=ð 	ˆV�ZŠZ˜‰_Œ_àˆ=ˆ=r   )ÚgoalÚgoalsÚcontextÚtoolsetsÚroleÚmodelÚis_batcha~  INSERT OR REPLACE INTO async_delegations
               (delegation_id, origin_session, origin_ui_session_id,
                parent_session_id, state, dispatched_at, updated_at,
                delivery_state, delivery_attempts, owner_pid,
                owner_started_at, task_json, origin_session_id)
               VALUES (?, ?, ?, ?, 'running', ?, ?, 'pending', 0, ?, ?, ?, ?)Údelegation_idÚsession_keyÚ Úorigin_ui_session_idÚparent_session_idÚdispatched_atr@   )ÚtimeÚgateway.statusrM   Ú
__import__Úgetpidr*   Ú_DB_LOCKrI   rC   rQ   ÚjsonÚdumpsÚ_prune_durable_records)rJ   ÚnowrM   r:   Útask_payloadr-   s   `     r   Ú_persist_dispatchrk   È   s  ø€ Ý
Œ)‰+Œ+€Cð Ø9Ð9Ð9Ð9Ð9Ð9Ø1Ð1µ*¸TÑ2BÔ2B×2IÒ2IÑ2KÔ2KÑLÔLÐÐøÝð  ð  ð  ØÐÐÐð øøøðð ð ð àXðñ ô €Lõ
 
ð 
ð 
•<‘>”>ð 
 TØ�ŠðQð �OÔ$ f§j¢j°ÀÑ&CÔ&CØ�ZŠZÐ.°Ñ3Ô3°V·Z²ZÐ@SÑ5TÔ5TØ�OÔ$ c­:°dÑ+;Ô+;×+BÒ+BÑ+DÔ+DØ�tœz¨,Ñ7Ô7Ø�ZŠZÐ+¨RÑ0Ô0ð	2ñ	
ô 	
ð 	
ð
ð 
ð 
ñ 
ô 
ð 
ð 
ð 
ð 
ð 
ð 
øøøð 
ð 
ð 
ð 
ð 
ð 
ð 
ñ 
ô 
ð 
ð 
ð 
ð 
ð 
ð 
øøøð 
ð 
ð 
ð 
õ ÑÔÐÐÐsH   –0A ÁAÁAÁ.EÁ=B-D6Ä*EÄ6D:	Ä:EÄ=D:	Ä>EÅEÅEr[   Ústrc                óÀ   — t           5  t          ¦   «         5 }|                     d| f¦  «         d d d ¦  «         n# 1 swxY w Y   d d d ¦  «         d S # 1 swxY w Y   d S )Nz3DELETE FROM async_delegations WHERE delegation_id=?)re   rI   rC   ©r[   r-   s     r   Ú_delete_durable_delegationro   å   s  € Ý	ð ^ð ^•<‘>”>ð ^ TØ�ŠÐJÈ]ÐL\Ñ]Ô]Ð]ð^ð ^ð ^ñ ^ô ^ð ^ð ^ð ^ð ^ð ^ð ^øøøð ^ð ^ð ^ð ^ð ^ð ^ð ^ñ ^ô ^ð ^ð ^ð ^ð ^ð ^ð ^ð ^øøøð ^ð ^ð ^ð ^ð ^ð ^s.   ˆA—;¯A»?	¿AÁ?	ÁAÁAÁAc                 ór  — t          j         ¦   «         } | t          z
  }t          5  t          ¦   «         5 }|                     d|f¦  «         |                     d¦  «                             ¦   «         d         }t          d|t          z
  ¦  «        }|r|                     d|f¦  «         |                     d¦  «                             ¦   «         d         }t          d|t          z
  ¦  «        }|r|                     d|f¦  «         ddd¦  «         n# 1 swxY w Y   ddd¦  «         dS # 1 swxY w Y   dS )zBBound terminal history, preferring delivered records for deletion.zQDELETE FROM async_delegations WHERE delivery_state='delivered' AND updated_at < ?zRSELECT COUNT(*) FROM async_delegations WHERE state NOT IN ('running','finalizing')r   aX  DELETE FROM async_delegations WHERE delegation_id IN (
                     SELECT delegation_id FROM async_delegations
                     WHERE state NOT IN ('running','finalizing')
                     ORDER BY CASE delivery_state WHEN 'delivered' THEN 0 ELSE 1 END,
                              updated_at ASC LIMIT ?
                   )z~SELECT COUNT(*) FROM async_delegations
               WHERE state NOT IN ('running','finalizing') AND delivery_state='pending'a  DELETE FROM async_delegations WHERE delegation_id IN (
                     SELECT delegation_id FROM async_delegations
                     WHERE state NOT IN ('running','finalizing') AND delivery_state='pending'
                     ORDER BY updated_at ASC LIMIT ?
                   )N)	ra   Ú_DURABLE_RETENTION_SECONDSre   rI   rC   ÚfetchoneÚmaxÚ_MAX_RETAINED_COMPLETEDÚ_MAX_DURABLE_PENDING)ri   Úcutoffr-   Úterminal_countÚexcessÚpending_countÚoverflows          r   rh   rh   ê   sÒ  € å
Œ)‰+Œ+€CØÕ-Ñ-€FÝ	ð  ð  •<‘>”>ð   TØ�ŠØ_ØˆIñ	
ô 	
ð 	
ð ŸšØ`ñ
ô 
ç
Š(‰*Œ*�Qôˆõ �Q˜Õ)@Ñ@ÑAÔAˆØð 		Ø�LŠLðð �	ñô ð ð Ÿšð[ñ
ô 
÷ Š(‰*Œ*�Qôˆõ �q˜-Õ*>Ñ>Ñ?Ô?ˆØð 	Ø�LŠLðð
 �ñô ð ð3 ð  ð  ñ  ô  ð  ð  ð  ð  ð  ð  øøøð  ð  ð  ð  ð  ð  ð  ñ  ô  ð  ð  ð  ð  ð  ð  ð  øøøð  ð  ð  ð  ð  ð  s5   ¥D,´CDÄD,ÄD	ÄD,ÄD	ÄD,Ä,D0Ä3D0ÚeventÚresultc                ó”  — t          j         ¦   «         }t          5  t          ¦   «         5 }|                     d|                      dd¦  «        |                      d|¦  «        |t          j        | ¦  «        t          j        |¦  «        | d         f¦  «         d d d ¦  «         n# 1 swxY w Y   d d d ¦  «         d S # 1 swxY w Y   d S )Nz­UPDATE async_delegations SET state=?, completed_at=?, updated_at=?,
               event_json=?, result_json=?, delivery_state='pending'
               WHERE delegation_id=?ÚstatusÚ	completedÚcompleted_atr[   )ra   re   rI   rC   rQ   rf   rg   )r{   r|   ri   r-   s       r   Ú_persist_completionr�     s8  € Ý
Œ)‰+Œ+€CÝ	ð 
ð 
•<‘>”>ð 
 TØ�Šð(ð �YŠY�x Ñ-Ô-¨u¯yªy¸ÈÑ/MÔ/MÈsÝŒZ˜ÑÔ¥¤
¨6Ñ 2Ô 2°E¸/Ô4JðLñ		
ô 	
ð 	
ð
ð 
ð 
ñ 
ô 
ð 
ð 
ð 
ð 
ð 
ð 
øøøð 
ð 
ð 
ð 
ð 
ð 
ð 
ñ 
ô 
ð 
ð 
ð 
ð 
ð 
ð 
ð 
øøøð 
ð 
ð 
ð 
ð 
ð 
s5   ›B=ªA/B%ÂB=Â%B)	Â)B=Â,B)	Â-B=Â=CÃCc                óä   — t           5  t          ¦   «         5 }|                     dt          j        ¦   «         | f¦  «         d d d ¦  «         n# 1 swxY w Y   d d d ¦  «         d S # 1 swxY w Y   d S )NzfUPDATE async_delegations SET delivery_attempts=delivery_attempts+1, updated_at=? WHERE delegation_id=?)re   rI   rC   ra   rn   s     r   Ú_note_delivery_attemptrƒ     sî   € Ý	ð 
ð 
•<‘>”>ð 
 TØ�ŠØtÝŒY‰[Œ[˜-Ð(ñ	
ô 	
ð 	
ð
ð 
ð 
ñ 
ô 
ð 
ð 
ð 
ð 
ð 
ð 
øøøð 
ð 
ð 
ð 
ð 
ð 
ð 
ñ 
ô 
ð 
ð 
ð 
ð 
ð 
ð 
ð 
øøøð 
ð 
ð 
ð 
ð 
ð 
s4   ˆA%—*AÁA%ÁA	ÁA%ÁA	ÁA%Á%A)Á,A)c                 óf  — 	 ddl m} m} n# t          $ r Y dS w xY wt	          j        ¦   «         }d}t
          5  t          ¦   «         5 }|                     d¦  «                             ¦   «         }|D �]�}|\	  }}}	}
}}}}}d}|rE | t          |¦  «        ¦  «        }|r+|�) |t          |¦  «        ¦  «        t          |¦  «        k    }|rŒ[t          j        |pd¦  «        }i dd“d	|“d
|“d|	“d|pd“d|
“d|                     dd¦  «        “d|                     d¦  «        “d|                     d¦  «        “d|                     d¦  «        “d|                     d¦  «        “d|                     d¦  «        “dt          |                     d¦  «        ¦  «        “dd“dd“dd“d|“d|i¥}dd|d         dœ}|                     d||t          j        |¦  «        t          j        |¦  «        |f¦  «         |dz  }�Œ‘	 ddd¦  «         n# 1 swxY w Y   ddd¦  «         n# 1 swxY w Y   |S ) zEClassify records whose owning process disappeared as outcome unknown.r   )Ú_pid_existsrM   a  SELECT delegation_id, origin_session, origin_ui_session_id,
                      parent_session_id, dispatched_at, owner_pid,
                      owner_started_at, task_json, origin_session_id
               FROM async_delegations WHERE state IN ('running','finalizing')FNz{}ÚtypeÚasync_delegationr[   r\   r^   r@   r]   r_   rT   rU   rV   rW   rX   rY   rZ   r~   ÚunknownÚsummaryÚerrorzLDelegation owner exited before recording a terminal result; outcome unknown.r`   r€   )r~   r‰   rŠ   z½UPDATE async_delegations SET state='unknown', completed_at=?,
                   updated_at=?, event_json=?, result_json=?, delivery_state='pending'
                   WHERE delegation_id=?r4   )rb   r…   rM   r*   ra   re   rI   rC   Úfetchallr   rf   ÚloadsrQ   Úboolrg   )r…   rM   ri   Ú	recoveredr-   Úrowsr6   r[   r\   Ú	origin_uiÚ	parent_idr`   ÚpidÚstartedr;   r@   ÚliveÚtaskr{   r|   s                       r   Úrecover_abandoned_delegationsr–   %  s�  € ðØFÐFÐFÐFÐFÐFÐFÐFÐFøÝð ð ð Øˆqˆqðøøøå
Œ)‰+Œ+€CØ€IÝ	ð 'ð '•<‘>”>ð ' TØ�|Š|ðQñ
ô 
÷
 Š(‰*Œ*ð 	ð ð  	ñ  	ˆCà;>ñ9ˆ]˜K¨°I¸}Ø�'˜9Ð&7ØˆDØð LØ"�{¥3 s¡8¤8Ñ,Ô,�Øð L˜GÐ/Ø1Ð1µ#°c±(´(Ñ;Ô;½sÀ7¹|¼|ÒK�DØð ØÝ”:˜iÐ/¨4Ñ0Ô0ˆDðØÐ*ðØ,;¸]ðà˜{ðà,BÀIðð
 $Ð%6Ð%<¸"ðð $ Yðð 17¸¿ºÀÈÑ8LÔ8Lðð ˜Ÿš 'Ñ*Ô*ðð -6°t·x²xÀ	Ñ7JÔ7Jðð ˜DŸHšH ZÑ0Ô0ðð 39¸$¿(º(À6Ñ:JÔ:Jðð ˜Ÿš 'Ñ*Ô*ðð -7½¸T¿XºXÀjÑ=QÔ=QÑ8RÔ8Rðð ˜)ðð &/°ðð Ðgðð   ðð 1?Àðð ˆEð !*°dÀUÈ7Ä^ÐTÐTˆFØ�LŠLð,ð �c�4œ: eÑ,Ô,­d¬j¸Ñ.@Ô.@À-ÐPñ	ô ð ð ˜‰NˆI‰IðA 	ð'ð 'ð 'ñ 'ô 'ð 'ð 'ð 'ð 'ð 'ð 'øøøð 'ð 'ð 'ð 'ð 'ð 'ð 'ñ 'ô 'ð 'ð 'ð 'ð 'ð 'ð 'øøøð 'ð 'ð 'ð 'ðP ÐsB   ‚ ‹
˜¸H&ÁF;HÈH&ÈH	ÈH&ÈH	ÈH&È&H*È-H*c                ó¬  — t          ¦   «          t          5  t          ¦   «         5 }|                     d¦  «                             ¦   «         }|D ]H\  }}t          j        |¦  «        }t          |t          ¦  «        rd|d<   |  	                    |¦  «         ŒI	 ddd¦  «         n# 1 swxY w Y   ddd¦  «         n# 1 swxY w Y   t          |¦  «        S )uz  Enqueue durable pending completions as fresh turns after process start.

    Every restored event is stamped ``restored=True`` (in-memory only â€” the
    stamp is added after the durable payload is deserialized and is never
    persisted). Restored events originate from a *previous* process, so no
    consumer in THIS process implicitly owns them: drain paths that run
    without an ownership filter (the legacy single-session behavior) must
    leave them queued for a consumer that can positively prove ownership,
    otherwise a brand-new session adopts a dead session's delegation
    results seconds after boot (#64484).
    zËSELECT delegation_id, event_json FROM async_delegations
               WHERE state != 'running' AND delivery_state='pending' AND event_json IS NOT NULL
               ORDER BY completed_at, delegation_idTÚrestoredN)r–   re   rI   rC   r‹   rf   rŒ   Ú
isinstanceÚdictÚputÚlen)Útarget_queuer-   r�   Ú_delegation_idÚpayloadÚevts         r   Úrestore_undelivered_completionsr¡   X  sV  € õ "Ñ#Ô#Ð#Ý	ð 
"ð 
"•<‘>”>ð 
" TØ�|Š|ð7ñ
ô 
÷ Š(‰*Œ*ð	 	ð
 (,ð 	"ð 	"Ñ#ˆN˜GÝ”*˜WÑ%Ô%ˆCÝ˜#�tÑ$Ô$ð 'Ø"&��J‘Ø×Ò˜SÑ!Ô!Ð!Ð!ð		"ð
"ð 
"ð 
"ñ 
"ô 
"ð 
"ð 
"ð 
"ð 
"ð 
"ð 
"øøøð 
"ð 
"ð 
"ð 
"ð 
"ð 
"ð 
"ñ 
"ô 
"ð 
"ð 
"ð 
"ð 
"ð 
"ð 
"øøøð 
"ð 
"ð 
"ð 
"õ ˆt‰9Œ9Ðs5   –B<¥A3B%ÂB<Â%B)	Â)B<Â,B)	Â-B<Â<C ÃC r�   c                ó  — t          j         ¦   «         }t          5  t          ¦   «         5 }|                     d||| f¦  «        }|j        dk    cddd¦  «         cddd¦  «         S # 1 swxY w Y   ddd¦  «         dS # 1 swxY w Y   dS )zDAtomically acknowledge successful injection of a durable completion.zšUPDATE async_delegations SET delivery_state='delivered', delivered_at=?, updated_at=?
               WHERE delegation_id=? AND delivery_state!='delivered'r4   N©ra   re   rI   rC   Úrowcount)r[   ri   r-   Úcurs       r   Úmark_completion_deliveredr¦   s  s)  € å
Œ)‰+Œ+€CÝ	ð !ð !•<‘>”>ð ! TØ�lŠlðHà�#�}Ð%ñ
ô 
ˆð
 Œ|˜qÒ ð!ð !ð !ð !ñ !ô !ð !ð !ð !ð !ð !ñ !ô !ð !ð !ð !ð !ð !ð !øøøð !ð !ð !ð !ð !ð !ð !ñ !ô !ð !ð !ð !ð !ð !ð !ð !øøøð !ð !ð !ð !ð !ð !ó4   ›A?ª$A'ÁA?Á'A+	Á+A?Á.A+	Á/A?Á?BÂBÚclaim_idc                óª  — t          j         ¦   «         }t          5  t          ¦   «         5 }|                     d| f¦  «                             ¦   «         }|€	 ddd¦  «         ddd¦  «         dS |                     d|||| |dz
  f¦  «        }|j        dk    cddd¦  «         cddd¦  «         S # 1 swxY w Y   ddd¦  «         dS # 1 swxY w Y   dS )zBClaim one pending completion across competing consumers/processes.zBSELECT delivery_state FROM async_delegations WHERE delegation_id=?NTa  UPDATE async_delegations SET delivery_claim=?, delivery_claimed_at=?,
                      delivery_attempts=delivery_attempts+1, updated_at=?
               WHERE delegation_id=? AND delivery_state='pending'
                 AND (delivery_claim IS NULL OR delivery_claimed_at < ?)i,  r4   )ra   re   rI   rC   rr   r¤   )r[   r¨   ri   r-   r6   r¥   s         r   Úclaim_completion_deliveryrª     s¯  € å
Œ)‰+Œ+€CÝ	ð !ð !•<‘>”>ð ! TØ�lŠlØPØÐñ
ô 
÷ Š(‰*Œ*ð 	ð ˆ;Øð!ð !ð !ñ !ô !ð !ð !ð !ð !ñ !ô !ð !ð !ð !ð �lŠlðLð �s˜C °°c±	Ð:ñ
ô 
ˆð Œ|˜qÒ ð!ð !ð !ð !ñ !ô !ð !ð !ð !ð !ð !ñ !ô !ð !ð !ð !ð !ð !ð !øøøð !ð !ð !ð !ð !ð !ð !ñ !ô !ð !ð !ð !ð !ð !ð !ð !øøøð !ð !ð !ð !ð !ð !s@   ›Cª-B0ÁCÁ/(B0ÂCÂ0B4	Â4CÂ7B4	Â8CÃCÃCr    ÚconsumerúOptional[str]c                ó.  — |                       d¦  «        dk    rdS t          |                       d¦  «        pd¦  «        }|sdS |› dt          d¦  «                             ¦   «         › dt	          j        ¦   «         j        › �}t          ||¦  «        r|ndS )zCClaim a durable delegation event; non-durable events need no token.r†   r‡   r]   r[   ú:rN   N)rQ   rl   rc   rd   ÚuuidÚuuid4Úhexrª   )r    r«   r[   r¨   s       r   Úclaim_event_deliveryr²   “  s™   € à
‡w‚wˆv�„Ð,Ò,Ð,ØˆrÝ˜Ÿš Ñ0Ô0Ð6°BÑ7Ô7€MØð ØˆrØÐKÐK�Z¨Ñ-Ô-×4Ò4Ñ6Ô6ÐKÐK½¼¹¼Ô9IÐKÐK€HÝ0°ÀÑIÔIÐSˆ8ˆ8ÈtÐSr   c           	     óà  — t          j         ¦   «         }t          5  t          ¦   «         5 }|                     d|| |t          f¦  «        }|j        dk    r:t                               d| t          ¦  «         	 ddd¦  «         ddd¦  «         dS |                     d|| |f¦  «        }|j        dk    cddd¦  «         cddd¦  «         S # 1 swxY w Y   ddd¦  «         dS # 1 swxY w Y   dS )uÖ  Release a failed delivery claim so another consumer may retry.

    Attempts are counted at claim time, so a row that keeps being claimed and
    released has burned real delivery attempts. Once the budget is exhausted
    the row converges to a terminal ``dropped`` state instead of returning to
    ``pending`` â€” otherwise an undeliverable completion replays on every
    gateway restart forever (restore_undelivered_completions only restores
    pending rows).
    a	  UPDATE async_delegations SET delivery_state='dropped',
                      delivery_claim=NULL, delivery_claimed_at=NULL, updated_at=?
               WHERE delegation_id=? AND delivery_state='pending'
                 AND delivery_claim=? AND delivery_attempts>=?r4   znAsync delegation %s exhausted its %d delivery attempts; marking terminally dropped (result remains queryable).NTzÖUPDATE async_delegations SET delivery_claim=NULL,
                      delivery_claimed_at=NULL, updated_at=?
               WHERE delegation_id=? AND delivery_state='pending'
                 AND delivery_claim=?)ra   re   rI   rC   Ú_MAX_DELIVERY_ATTEMPTSr¤   ÚloggerÚwarning)r[   r¨   ri   r-   Úcappedr¥   s         r   Úrelease_completion_deliveryr¸   ž  sÒ  € õ Œ)‰+Œ+€CÝ	ð !ð !•<‘>”>ð ! TØ—’ðBð �- Õ+AÐBñ
ô 
ˆð Œ?˜aÒÐÝ�NŠNðIàÕ5ñô ð ð
 ð!ð !ð !ñ !ô !ð !ð !ð !ð !ñ !ô !ð !ð !ð !ð �lŠlð)ð �- Ð*ñ
ô 
ˆð Œ|˜qÒ ð-!ð !ð !ð !ñ !ô !ð !ð !ð !ð !ð !ñ !ô !ð !ð !ð !ð !ð !ð !øøøð !ð !ð !ð !ð !ð !ð !ñ !ô !ð !ð !ð !ð !ð !ð !ð !øøøð !ð !ð !ð !ð !ð !sA   ›C#ªACÁ7C#Â#CÂ2C#ÃC	ÃC#ÃC	ÃC#Ã#C'Ã*C'c                ó  — t          j         ¦   «         }t          5  t          ¦   «         5 }|                     d|| |f¦  «        }|j        dk    cddd¦  «         cddd¦  «         S # 1 swxY w Y   ddd¦  «         dS # 1 swxY w Y   dS )u½  Terminally drop a claimed completion that can never be delivered.

    Used when the delivery target is permanently gone â€” the spawning session
    ended at an explicit user boundary (/new, reset) rather than a compression
    rotation. Marking the row ``dropped`` (not ``delivered``) keeps the ack
    honest, and (not ``pending``) keeps restart recovery from replaying a
    completion that will be fail-closed dropped again every time.
    a  UPDATE async_delegations SET delivery_state='dropped',
                      updated_at=?, delivery_claim=NULL,
                      delivery_claimed_at=NULL
               WHERE delegation_id=? AND delivery_state='pending'
                 AND delivery_claim=?r4   Nr£   ©r[   r¨   ri   r-   r¥   s        r   Údrop_completion_deliveryr»   Â  s,  € õ Œ)‰+Œ+€CÝ	ð 	!ð 	!•<‘>”>ð 	! TØ�lŠlð)ð
 �- Ð*ñ
ô 
ˆð Œ|˜qÒ ð	!ð 	!ð 	!ð 	!ñ 	!ô 	!ð 	!ð 	!ð 	!ð 	!ð 	!ñ 	!ô 	!ð 	!ð 	!ð 	!ð 	!ð 	!ð 	!øøøð 	!ð 	!ð 	!ð 	!ð 	!ð 	!ð 	!ñ 	!ô 	!ð 	!ð 	!ð 	!ð 	!ð 	!ð 	!ð 	!øøøð 	!ð 	!ð 	!ð 	!ð 	!ð 	!r§   c           	     ó  — t          j         ¦   «         }t          5  t          ¦   «         5 }|                     d||| |f¦  «        }|j        dk    cddd¦  «         cddd¦  «         S # 1 swxY w Y   ddd¦  «         dS # 1 swxY w Y   dS )z;Acknowledge acceptance for the consumer holding this claim.a  UPDATE async_delegations SET delivery_state='delivered',
                      delivered_at=?, updated_at=?, delivery_claim=NULL,
                      delivery_claimed_at=NULL
               WHERE delegation_id=? AND delivery_state='pending'
                 AND delivery_claim=?r4   Nr£   rº   s        r   Úcomplete_completion_deliveryr½   Ø  s,  € å
Œ)‰+Œ+€CÝ	ð 	!ð 	!•<‘>”>ð 	! TØ�lŠlð)ð
 �#�} hÐ/ñ
ô 
ˆð Œ|˜qÒ ð	!ð 	!ð 	!ð 	!ñ 	!ô 	!ð 	!ð 	!ð 	!ð 	!ð 	!ñ 	!ô 	!ð 	!ð 	!ð 	!ð 	!ð 	!ð 	!øøøð 	!ð 	!ð 	!ð 	!ð 	!ð 	!ð 	!ñ 	!ô 	!ð 	!ð 	!ð 	!ð 	!ð 	!ð 	!ð 	!øøøð 	!ð 	!ð 	!ð 	!ð 	!ð 	!s4   ›B ª%A(ÁB Á(A,	Á,B Á/A,	Á0B Â BÂBc                ó¨   — |rM|                       d¦  «        dk    r6t          t          |                       d¦  «        pd¦  «        |¦  «         d S d S d S ©Nr†   r‡   r[   r]   )rQ   r½   rl   ©r    r¨   s     r   Úcomplete_event_deliveryrÁ   ç  sa   € Øð T�C—G’G˜F‘O”OÐ'9Ò9Ð9Ý$¥S¨¯ª°Ñ)AÔ)AÐ)GÀRÑ%HÔ%HÈ(ÑSÔSÐSÐSÐSðTð TÐ9Ð9r   c                ó¨   — |rM|                       d¦  «        dk    r6t          t          |                       d¦  «        pd¦  «        |¦  «         d S d S d S r¿   )rQ   r¸   rl   rÀ   s     r   Úrelease_event_deliveryrÃ   ì  sa   € Øð S�C—G’G˜F‘O”OÐ'9Ò9Ð9Ý#¥C¨¯ª°Ñ(@Ô(@Ð(FÀBÑ$GÔ$GÈÑRÔRÐRÐRÐRðSð SÐ9Ð9r   úOptional[Dict[str, Any]]c           
     óš  — t           5  t          ¦   «         5 }|                     d| f¦  «                             ¦   «         }d d d ¦  «         n# 1 swxY w Y   d d d ¦  «         n# 1 swxY w Y   |€d S | |d         |d         |d         |d         |d         rt	          j        |d         ¦  «        nd |d         |d         |d	         pd
dœ	S )NzäSELECT origin_session, state, dispatched_at, completed_at,
                      result_json, delivery_state, delivery_attempts,
                      origin_session_id
               FROM async_delegations WHERE delegation_id=?r   r4   é   r   é   é   é   é   r]   )	r[   Úorigin_sessionÚstater`   r€   r|   Údelivery_stateÚdelivery_attemptsr@   )re   rI   rC   rr   rf   rŒ   )r[   r-   r6   s      r   Úget_durable_delegationrÏ   ñ  sV  € Ý	ð ð •<‘>”>ð  TØ�lŠlð?ð BOÐ@Pñ	
ô 
÷
 Š(‰*Œ*ð 	ðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ð ð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ð €{Øˆtà&¸#¸a¼&È3ÈqÌ6Ø˜Qœ°°Q´Ø(+¨A¬Ð8•$”*˜S œVÑ$Ô$Ð$°DØ˜aœ&°s¸1´vØ  œV˜\ rðð ð s4   ˆA$—*AÁA$ÁA	ÁA$ÁA	ÁA$Á$A(Á+A(Úmax_workersr   c                óœ   — t           5  t          �| t          k    rt          | d¬¦  «        a| at          cddd¦  «         S # 1 swxY w Y   dS )u  Lazily create (or grow) the shared daemon executor.

    We never shrink â€” ThreadPoolExecutor can't resize â€” but if the configured
    cap grows between calls we rebuild a larger pool. Existing in-flight
    futures keep running on the old pool until it's garbage collected.
    Nzasync-delegate)rÐ   Úthread_name_prefix)Ú_executor_lockr   r   Ú_DaemonThreadPoolExecutor)rÐ   s    r   Ú_get_executorrÕ     s¤   € õ 
ð ð ÝÐ Õ.CÒ CÐ Cå1Ø'Ø#3ðñ ô ˆIð %0Ð!Ýðð ð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ð ð s   ˆ,AÁAÁAc                 ó¤   — t           5  t          d„ t                               ¦   «         D ¦   «         ¦  «        cddd¦  «         S # 1 swxY w Y   dS )a~  Number of async delegation UNITS currently running.

    A unit is one dispatch: a single subagent OR a whole fan-out batch. A batch
    counts as ONE here because it occupies one async-pool slot (the capacity
    semantics ``dispatch_async_delegation_batch`` relies on). For the count of
    actual concurrent child subagents (batch expanded), use
    ``active_task_count()``.
    c              3  óH   K  — | ]}|                      d ¦  «        dv ¯dV — ŒdS )r~   >   ÚrunningÚstallingÚ
finalizingr4   NrP   ©r5   Úrs     r   ú	<genexpr>zactive_count.<locals>.<genexpr>!  sD   è è € ð 
ð 
ØØ�uŠu�X‰ŒÐ"GÐGÐGð ØGÐGÐGÐGð
ð 
r   N©Ú_records_lockÚsumr   Úvaluesr   r   r   Úactive_countrâ     s¡   € õ 
ð 
ð 
Ýð 
ð 
Ý—’Ñ(Ô(ð
ñ 
ô 
ñ 
ô 
ð
ð 
ð 
ð 
ñ 
ô 
ð 
ð 
ð 
ð 
ð 
ð 
øøøð 
ð 
ð 
ð 
ð 
ð 
ó   ˆ0AÁA	ÁA	r^   c                ó²   ‡ — ‰ sdS t           5  t          ˆ fd„t                               ¦   «         D ¦   «         ¦  «        cddd¦  «         S # 1 swxY w Y   dS )z9Number of live async delegations owned by one UI session.r   c              3  óš   •K  — | ]E}|                      d ¦  «        dv r,t          |                      d¦  «        pd¦  «        ‰k    ¯AdV — ŒFdS )r~   >   rØ   rÙ   rÚ   r^   r]   r4   N)rQ   rl   )r5   rÜ   r^   s     €r   rÝ   z%active_for_session.<locals>.<genexpr>,  sw   øè è € ð 
ð 
àØ�uŠu�X‰ŒÐ"GÐGÐGÝ�A—E’EÐ0Ñ1Ô1Ð7°RÑ8Ô8Ø#ò$ð $ð ð$ð $ð $ð $ð	
ð 
r   NrÞ   )r^   s   `r   Úactive_for_sessionræ   '  s·   ø€ àð ØˆqÝ	ð 
ð 
Ýð 
ð 
ð 
ð 
å—_’_Ñ&Ô&ð
ñ 
ô 
ñ 
ô 
ð
ð 
ð 
ð 
ñ 
ô 
ð 
ð 
ð 
ð 
ð 
ð 
øøøð 
ð 
ð 
ð 
ð 
ð 
s   �2AÁAÁAc                 óx  — t           5  d} t                               ¦   «         D ]|}|                     d¦  «        dvrŒ|                     d¦  «        rH|                     d¦  «        }| t	          |t
          t          f¦  «        r|rt          |¦  «        ndz  } Œw| dz  } Œ}| cddd¦  «         S # 1 swxY w Y   dS )aè  Number of async delegation TASKS (child subagents) currently running.

    Unlike ``active_count()`` (units/slots), this expands a batch to its child
    count: a running batch of N tasks contributes N, a single subagent
    contributes 1. This is the truthful "how many subagents are actually
    working right now" figure for observability, where a 3-task batch shown as
    "1" undercounts real concurrent work. Falls back to counting a batch as 1
    if its goal list is missing.
    r   r~   >   rØ   rÚ   rZ   rU   r4   N)rß   r   rá   rQ   r™   ÚlistÚtuplerœ   )ÚtotalrÜ   rU   s      r   Úactive_task_countrë   5  s  € õ 
ð 
ð 
ØˆÝ—’Ñ"Ô"ð 	ð 	ˆAØ�uŠu�X‰ŒÐ&?Ð?Ð?ØØ�uŠu�ZÑ Ô ð ØŸš˜g™œ�Ø¥z°%½$Å¸Ñ'GÔ'GÐXÈEÐX�˜U™œ˜ÐWXÑX��à˜‘
��Øð
ð 
ð 
ð 
ñ 
ô 
ð 
ð 
ð 
ð 
ð 
ð 
øøøð 
ð 
ð 
ð 
ð 
ð 
s   ˆBB/Â/B3Â6B3r]   ©r\   r^   r_   r\   r_   c               óþ   — |r(t          |                      d¦  «        pd¦  «        |k    pS|o't          |                      d¦  «        pd¦  «        |k    p)|o't          |                      d¦  «        pd¦  «        |k    S )Nr^   r]   r\   r_   )rl   rQ   )rJ   r\   r^   r_   s       r   Ú_matches_session_selectorsrî   L  s‹   € ð 
Ð	g¥# f§j¢jÐ1GÑ&HÔ&HÐ&NÈBÑ"OÔ"OÐSgÒ"gð 	cØÐO�C §
¢
¨=Ñ 9Ô 9Ð ?¸RÑ@Ô@ÀKÒOð	càÐa¥# f§j¢jÐ1DÑ&EÔ&EÐ&KÈÑ"LÔ"LÐPaÒ"aðr   c                óÂ   ‡ ‡‡— ‰ s‰s‰sdS t           5  t          ˆˆˆ fd„t                               ¦   «         D ¦   «         ¦  «        cddd¦  «         S # 1 swxY w Y   dS )u®   Whether a session still owns any live async delegation.

    Live = running / stalling / finalizing â€” the same states the reapers'
    keepalive treats as active work.
    Fc              3  ól   •K  — | ].}|                      d ¦  «        dv ot          |‰‰‰¬¦  «        V — Œ/dS )r~   >   rØ   rÙ   rÚ   rì   N©rQ   rî   ©r5   rÜ   r^   r_   r\   s     €€€r   rÝ   z'has_live_for_session.<locals>.<genexpr>g  sl   øè è € ð 	
ð 	
ð ð �EŠE�(‰OŒOÐDÐDð Ý*ØØ'Ø%9Ø"3ð	ñ ô ð	
ð 	
ð 	
ð 	
ð 	
ð 	
r   N)rß   Úanyr   rá   rì   s   ```r   Úhas_live_for_sessionrô   Z  s×   øøø€ ð ð Ð3ð Ð<Mð ØˆuÝ	ð 

ð 

Ýð 	
ð 	
ð 	
ð 	
ð 	
ð 	
õ —_’_Ñ&Ô&ð	
ñ 	
ô 	
ñ 	
ô 	
ð

ð 

ð 

ð 

ñ 

ô 

ð 

ð 

ð 

ð 

ð 

ð 

øøøð 

ð 

ð 

ð 

ð 

ð 

s   “4AÁAÁAc                 óH   — dt          j        ¦   «         j        d d…         › �S )NÚdeleg_r   )r¯   r°   r±   r   r   r   Ú_new_delegation_idr÷   s  s"   € Ø*•D”J‘L”LÔ$ R a RÔ(Ð*Ð*Ð*r   c                 ó.  — d„ t                                ¦   «         D ¦   «         } t          | ¦  «        t          k    rdS |                      d„ ¬¦  «         | dt          | ¦  «        t          z
  …         D ] \  }}t                                |d¦  «         Œ!dS )ziDrop the oldest completed records beyond the retention cap.

    Caller must hold ``_records_lock``.
    c                óN   — g | ]"\  }}|                      d ¦  «        dk    ¯||f‘Œ#S )r~   rØ   rP   )r5   ÚridrÜ   s      r   ú
<listcomp>z+_prune_completed_locked.<locals>.<listcomp>|  s?   € ð ð ð áˆC�Ø�5Š5�‰?Œ?˜iÒ'Ð'ð 
ˆaˆà'Ð'Ð'r   Nc                ór   — | d                               d¦  «        p| d                               d¦  «        pdS )Nr4   r€   r`   r   rP   )Úkvs    r   ú<lambda>z)_prune_completed_locked.<locals>.<lambda>„  s1   €  " Q¤%§)¢)¨NÑ";Ô";Ð"^¸rÀ!¼u¿yºyÈÑ?YÔ?YÐ"^Ð]^€ r   )rR   )r   Úitemsrœ   rt   ÚsortÚpop)r   rú   Ú_s      r   Ú_prune_completed_lockedr  w  s¦   € ð
ð å—n’nÑ&Ô&ðñ ô €Iõ
 ˆ9�~„~Õ0Ò0Ð0Øˆà‡N‚NÐ^Ð^€NÑ_Ô_Ð_ØÐF�c )™nœnÕ/FÑFÐFÔGð  ð  ‰ˆˆQÝ�Š�S˜$ÑÔÐÐð ð  r   c                 ór   — 	 ddl m}   | dd¦  «        dk    rdS  | dd¦  «        pdS # t          $ r Y dS w xY w)u·  Raw session id of the ORIGINATING api_server request, or ``""``.

    The obvious source â€” ``HERMES_SESSION_ID`` via ``get_session_env`` â€” is
    NOT safe to read at dispatch time: constructing a child agent
    (``agent/agent_init.py``) calls ``set_current_session_id(child.session_id)``,
    clobbering that ContextVar *and* ``os.environ`` with the subagent's
    internal ``{timestamp}_{uuid}`` id moments before the dispatch code reads
    it, so the completion wake would self-post into the subagent's own
    (unread) session instead of the spawner's.

    The request-scoped ``HERMES_SESSION_CHAT_ID`` binding survives child
    construction: ``_bind_api_server_session`` binds ``chat_id`` to the raw
    ``X-Hermes-Session-Id``, and its only writer is ``set_session_vars`` â€”
    ``set_current_session_id`` never touches it. Gate on the platform: on
    push platforms ``chat_id`` is a chat, not a session, so yield ``""``
    there.
    r   ©Úget_session_envÚHERMES_SESSION_PLATFORMr]   Ú
api_serverÚHERMES_SESSION_CHAT_ID)Úgateway.session_contextr  r*   r  s    r   Ú_current_origin_session_idr  ‰  sp   € ð$Ø;Ð;Ð;Ð;Ð;Ð;àˆ?Ð4°bÑ9Ô9¸\ÒIÐIØ�2ØˆÐ7¸Ñ<Ô<ÐBÀÐBøÝð ð ð Øˆrˆrðøøøs   ‚( š( ¨
6µ6)r_   r^   r@   Úinterrupt_fnÚmax_async_childrenÚprogress_fnrT   rV   rW   úOptional[List[str]]rX   rY   ÚrunnerúCallable[[], Dict[str, Any]]r@   r  úOptional[Callable[[], None]]r  r  úOptional[Callable[[], tuple]]c                ó¦  ‡‡‡— t          ¦   «         Št          j        ¦   «         Ši d‰“d| “d|“d|rt          |¦  «        nd“d|“d|“d|“d	|“d
|	“d|“dd“d‰“dd“d|
“d|“dd“d‰“ddi¥}t          5  t	          d„ t
                               ¦   «         D ¦   «         ¦  «        }||k    rdd|› d�dœcddd¦  «         S |t
          ‰<   ddd¦  «         n# 1 swxY w Y   t          |¦  «         t          |¦  «        }d$ˆˆˆfd„}	 | 	                    t          |¦  «        ¦  «         nh# t          $ r[}t          5  t
                               ‰d¦  «         ddd¦  «         n# 1 swxY w Y   t          ‰¦  «         dd|› �dœcY d}~S d}~ww xY w|�t          ¦   «          t                               d‰|pd| pd dd!…         ¦  «         d"‰d#œS )%a  Spawn ``runner`` on the daemon executor and return a handle immediately.

    Parameters
    ----------
    goal, context, toolsets, role, model
        The dispatch-time task spec, captured verbatim for the rich
        completion block.
    session_key
        The gateway session_key (from ``tools.approval.get_current_session_key``)
        captured on the parent thread BEFORE dispatch, because the daemon
        worker thread won't carry the contextvar. Used to route the
        completion back to the originating session.
    parent_session_id
        The durable ``state.db`` session id of the parent agent that spawned
        the delegation. Carried on the completion event so the gateway can
        pin routing to the spawning session instead of recovering the latest
        ``ended_at IS NULL`` row for the peer tuple (#57498).
    runner
        Zero-arg callable that builds + runs the child and returns the same
        result dict ``_run_single_child`` produces. Runs on the worker thread.
    interrupt_fn
        Optional callable to signal the child to stop (used on shutdown /
        explicit cancel).
    progress_fn
        Optional zero-arg callable returning ``(token, in_tool)`` where
        ``token`` is any comparable snapshot of the child's progress (api
        call count + current tool) and ``in_tool`` says whether the child is
        currently inside a tool call. Sampled by the stale monitor; a frozen
        token past the stale threshold marks the delegation stuck (see the
        stale-detection block at the top of this module). When omitted, the
        delegation is not monitored.
    max_async_children
        Concurrency cap. When at capacity the dispatch is REJECTED (the caller
        should fall back to sync or tell the user) rather than queued, so a
        runaway model can't pile up unbounded background work.

    Returns
    -------
    dict
        ``{"status": "dispatched", "delegation_id": ...}`` on success, or
        ``{"status": "rejected", "error": ...}`` when at capacity.
    r[   rT   rV   rW   NrX   rY   r\   r^   r@   r_   r~   rØ   r`   r€   r  r  Ú_progress_tokenÚ_progress_tsÚ_interrupted_atc              3  óH   K  — | ]}|                      d ¦  «        dv ¯dV — ŒdS ©r~   ©rØ   rÙ   r4   NrP   rÛ   s     r   rÝ   z,dispatch_async_delegation.<locals>.<genexpr>ú  óD   è è € ð 
ð 
ØØ�uŠu�X‰ŒÐ"9Ð9Ð9ð Ø9Ð9Ð9Ð9ð
ð 
r   Úrejectedú#Async delegation capacity reached (zà running). Wait for one to finish (its result will re-enter the chat), or run this task synchronously (background=false). Raise delegation.max_concurrent_children in config.yaml to allow more concurrent background subagents.©r~   rŠ   r   r/   c            	     ó’  •— i } d}	  ‰¦   «         pi } |                       d¦  «        pd}nu# t          $ rh}t                               d‰¦  «         dd t	          |¦  «        j        › d|› �dt          t          j        ¦   «         ‰z
  d¦  «        dœ} d}Y d }~nd }~ww xY wt          ‰| |¦  «         d S # t          ‰| |¦  «         w xY w)	NrŠ   r~   r   zAsync delegation %s crashedú: r   rÆ   )r~   r‰   rŠ   Ú	api_callsÚduration_seconds)	rQ   r*   rµ   Ú	exceptionr†   Ú__name__Úroundra   Ú	_finalize)r|   r~   Úexcr[   r`   r  s      €€€r   Ú_workerz*dispatch_async_delegation.<locals>._worker  sù   ø€ Ø!#ˆØˆð	5Ø�V‘X”X�^ ˆFØ—Z’Z Ñ)Ô)Ð8¨[ˆFˆFøÝð 		ð 		ð 		Ý×ÒÐ:¸MÑJÔJÐJà!ØÝ  ™IœIÔ.Ð7Ð7°#Ð7Ð7ØÝ$)­$¬)©+¬+¸Ñ*EÀqÑ$IÔ$Iðð ˆFð ˆFˆFˆFˆFˆFˆFøøøøð		øøøõ �m V¨VÑ4Ô4Ð4Ð4Ð4ø�I�m V¨VÑ4Ô4Ð4Ð4øøøs,   ‡#+ ªB3 «
BµABÂB3 ÂBÂB3 Â3Cz%Failed to schedule async delegation: z3Dispatched async delegation %s (session_key=%s): %sú<cli>r]   éP   Ú
dispatched©r~   r[   ©r   r/   )r÷   ra   rè   rß   rà   r   rá   rk   rÕ   Úsubmitr   r*   r  ro   Ú_ensure_stale_monitorrµ   Úinfo)rT   rV   rW   rX   rY   r\   r_   r  r^   r@   r  r  r  rJ   rØ   Úexecutorr(  r'  r[   r`   s          `          @@r   Údispatch_async_delegationr2  ¥  sŸ  øøø€ õt 'Ñ(Ô(€MÝ”I‘K”K€MðØ˜ðà�ðð 	�7ðð 	 hÐ8•D˜‘N”N�N°Dð	ð
 	�ðð 	�ðð 	�{ðð 	Ð 4ðð 	Ð.ðð 	Ð.ðð 	�)ðð 	˜ðð 	˜ðð 	˜ðð 	�{ðð" 	˜4ð#ð$ 	˜ð%ð& 	˜4ð'ð €Fõ0 
ð )ð )Ýð 
ð 
Ý—’Ñ(Ô(ð
ñ 
ô 
ñ 
ô 
ˆð Ð(Ò(Ð(à$ðRÐ:Lð Rð Rð Rð	ð 	ð)ð )ð )ð )ñ )ô )ð )ð )ð  #)��Ñð!)ð )ð )ñ )ô )ð )ð )ð )ð )ð )ð )øøøð )ð )ð )ð )õ$ �fÑÔÐÝÐ/Ñ0Ô0€Hð5ð 5ð 5ð 5ð 5ð 5ð 5ð 5ð&
ð 	�ŠÕ3°GÑ<Ô<Ñ=Ô=Ð=Ð=øÝð 
ð 
ð 
Ýð 	.ð 	.Ý�LŠL˜¨Ñ-Ô-Ð-ð	.ð 	.ð 	.ñ 	.ô 	.ð 	.ð 	.ð 	.ð 	.ð 	.ð 	.øøøð 	.ð 	.ð 	.ð 	.å" =Ñ1Ô1Ð1à ØB¸SÐBÐBð
ð 
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
øøøøð	
øøøð ÐÝÑÔÐå
‡K‚KØ=Ø�{Ð- g°°
¸¸C¸R¸CÔ/@ñô ð ð #°]ÐCÐCÐCsZ   Á6?CÃ
CÃCÃCÄ
"D- Ä-
FÄ7FÄ>E&ÅFÅ&E*	Å*FÅ-E*	Å.FÆFÆFr~   c                óx   — t          | ¦  «        }|€dS |\  }}t          |||¦  «         t          | |¦  «         dS )zDMark a record complete and push the completion event onto the queue.N)Ú_begin_finalizationÚ_push_completion_eventÚ_finish_finalization)r[   r|   r~   ÚclaimedÚevent_recordÚ_interrupt_fns         r   r&  r&  7  sK   € å! -Ñ0Ô0€GØ€ØˆØ")Ñ€L�-å˜<¨°Ñ8Ô8Ð8Ý˜¨Ñ/Ô/Ð/Ð/Ð/r   ú=Optional[tuple[Dict[str, Any], Optional[Callable[[], None]]]]c                ó\  — t           5  t                               | ¦  «        }|�|                     d¦  «        dvr	 ddd¦  «         dS d|d<   t          j        ¦   «         |d<   |                     d¦  «        }d|d<   d|d<   t	          |¦  «        }ddd¦  «         n# 1 swxY w Y   ||fS )zCAtomically claim terminal delivery while keeping the record active.Nr~   r  rÚ   r€   r  r  )rß   r   rQ   ra   rš   )r[   rJ   r  r8  s       r   r4  r4  B  s  € õ 
ð $ð $Ý—’˜mÑ,Ô,ˆØˆ>˜VŸZšZ¨Ñ1Ô1Ð9PÐPÐPØð$ð $ð $ñ $ô $ð $ð $ð $ð (ˆˆxÑÝ!%¤¡¤ˆˆ~ÑØ—z’z .Ñ1Ô1ˆØ!%ˆˆ~ÑØ $ˆˆ}ÑÝ˜F‘|”|ˆð$ð $ð $ñ $ô $ð $ð $ð $ð $ð $ð $øøøð $ð $ð $ð $ð ˜Ð%Ð%s   ˆ5BÁ
A	BÂB#Â&B#c                ó¤   — t           5  t                               | ¦  «        }|�||d<   t          ¦   «          d d d ¦  «         d S # 1 swxY w Y   d S )Nr~   )rß   r   rQ   r  )r[   r~   rJ   s      r   r6  r6  W  s™   € Ý	ð "ð "Ý—’˜mÑ,Ô,ˆØÐØ%ˆF�8ÑÝÑ!Ô!Ð!ð	"ð "ð "ñ "ô "ð "ð "ð "ð "ð "ð "ð "øøøð "ð "ð "ð "ð "ð "rã   c           	     ó^  — 	 ddl m} nG# t          $ r:}t                               d|                      d¦  «        |¦  «         Y d}~dS d}~ww xY w|                     d¦  «        }|                     d¦  «        }|                      d¦  «        pt          j        ¦   «         }|                      d	¦  «        pt          j        ¦   «         }i d
d“d|                      d¦  «        “d|                      dd¦  «        “d|                      dd¦  «        “d|                      dd¦  «        “d|                      d¦  «        “d|                      dd¦  «        “d|                      d¦  «        “d|                      d¦  «        “d|                      d¦  «        “d|                     d¦  «        p|                      d¦  «        “d|“d|“d|“d|                     dd¦  «        “d|                     dt          ||z
  d¦  «        ¦  «        “d|“||                     d¦  «        dœ¥}	dD ]}
|
|v r||
         |	|
<   Œt          |	|¦  «         	 |j	         
                    |	¦  «         dS # t          $ r:}t                               d|                      d¦  «        |¦  «         Y d}~dS d}~ww xY w)zÇPush a type='async_delegation' event onto the shared completion queue.

    Best-effort: a failure here must not crash the worker, but it WOULD mean a
    silently-lost result, so we log loudly.
    r   ©Úprocess_registryzPAsync delegation %s finished but process_registry import failed; result lost: %sr[   Nr‰   rŠ   r`   r€   r†   r‡   r\   r]   r^   r@   r_   rT   rV   rW   rX   rY   r~   r!  r"  rÆ   Úexit_reason)r€   r@  ©Ústalled_after_quiet_secondsÚstall_threshold_secondsÚstall_phaseÚstall_grace_secondszHAsync delegation %s: failed to enqueue completion event; result lost: %s)Útools.process_registryr?  r*   rµ   rŠ   rQ   ra   r%  r�   Úcompletion_queuer›   )rJ   r|   r~   r?  r'  r‰   rŠ   r`   r€   r    Ú_ks              r   r5  r5  _  sN  € ðØ;Ð;Ð;Ð;Ð;Ð;Ð;øÝð ð ð Ý�Šðà�JŠJ�Ñ'Ô'¨ñ	
ô 	
ð 	
ð
 	ˆˆˆˆˆøøøøðøøøð �jŠj˜Ñ#Ô#€GØ�JŠJ�wÑÔ€EØ—J’J˜Ñ/Ô/Ð>µ4´9±;´;€MØ—:’:˜nÑ-Ô-Ð<µ´±´€LðØÐ"ðà˜Ÿš OÑ4Ô4ðð
 	�v—z’z -°Ñ4Ô4ðð 	 §
¢
Ð+AÀ2Ñ FÔ Fðð 	˜VŸZšZÐ(;¸RÑ@Ô@ðð 	˜VŸZšZÐ(;Ñ<Ô<ðð 	�—
’
˜6 2Ñ&Ô&ðð 	�6—:’:˜iÑ(Ô(ðð 	�F—J’J˜zÑ*Ô*ðð 	�—
’
˜6Ñ"Ô"ðð 	�—’˜GÑ$Ô$Ð;¨¯
ª
°7Ñ(;Ô(;ðð 	�&ðð 	�7ðð  	�ð!ð" 	�V—Z’Z ¨QÑ/Ô/ð#ð$ 	˜FŸJšJØ¥ l°]Ñ&BÀAÑ FÔ Fñ
ô 
ð%ð* 	˜ð+ð, %Ø—z’z -Ñ0Ô0ð/ð ð €Cð6ð !ð !ˆð �ˆ<ˆ<Ø˜R”jˆC�‰GøÝ˜˜VÑ$Ô$Ð$ð
ØÔ)×-Ò-¨cÑ2Ô2Ð2Ð2Ð2øÝð 
ð 
ð 
Ý�Šðà�JŠJ�Ñ'Ô'¨ñ	
ô 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
øøøøð
øøøs,   ‚	 ‰
A“/AÁAÉI( É(
J,É2/J'Ê'J,)r_   r^   r@   r  r  r[   r  rU   ú	List[str]c                ó8  ‡‡‡— ‰pt          ¦   «         Št          j        ¦   «         Št          | ¦  «        }|dk    r| d         n$|› d�d                     d„ | D ¦   «         ¦  «        z   }i d‰“d|“dt	          | ¦  «        “d	|“d
|rt	          |¦  «        nd“d|“d|“d|“d|“d|	“d|“dd“d‰“dd“d|
“dd“d|“d‰ddœ¥}t
          5  t          d„ t                               ¦   «         D ¦   «         ¦  «        }||k    rdd|› d�dœcddd¦  «         S |t          ‰<   ddd¦  «         n# 1 swxY w Y   t          |¦  «         t          |¦  «        }d(ˆˆˆfd"„}	 |                     t          |¦  «        ¦  «         nh# t          $ r[}t
          5  t                               ‰d¦  «         ddd¦  «         n# 1 swxY w Y   t          ‰¦  «         dd#|› �dœcY d}~S d}~ww xY w|�t!          ¦   «          t"                               d$‰||pd%¦  «         d&‰d'œS ))u+  Dispatch a WHOLE fan-out batch as ONE background unit.

    Unlike ``dispatch_async_delegation`` (which backs a single subagent),
    ``runner`` here runs the entire batch â€” it builds and joins on every child
    in parallel and returns the combined ``{"results": [...],
    "total_duration_seconds": N}`` dict that the synchronous path would have
    returned. We occupy ONE async slot for the whole batch (the in-batch
    parallelism is bounded separately by ``max_concurrent_children``), so a
    single ``delegate_task`` fan-out never exhausts the async pool by itself.

    When the batch finishes, a SINGLE completion event is pushed onto the
    shared ``process_registry.completion_queue`` carrying the full per-task
    ``results`` list, so the consolidated summaries re-enter the conversation
    as one message once every child is done â€” the chat is never blocked while
    they run.

    Returns ``{"status": "dispatched", "delegation_id": ...}`` on success or
    ``{"status": "rejected", "error": ...}`` when the async pool is at
    capacity.
    r4   r   z parallel subagents: z; c              3  ó*   K  — | ]}|d d…         V — Œd S )Né(   r   )r5   Úgs     r   rÝ   z2dispatch_async_delegation_batch.<locals>.<genexpr>Î  s+   è è € ÐG^ÐG^ÐSTÈÈ#È2È#ÌÐG^ÐG^ÐG^ÐG^ÐG^ÐG^r   r[   rT   rU   rV   rW   NrX   rY   r\   r^   r@   r_   r~   rØ   r`   r€   r  rZ   Tr  )r  r  r  c              3  óH   K  — | ]}|                      d ¦  «        dv ¯dV — ŒdS r  rP   rÛ   s     r   rÝ   z2dispatch_async_delegation_batch.<locals>.<genexpr>ç  r  r   r  r  z¬ running). Wait for one to finish (its result will re-enter the chat), or raise delegation.max_concurrent_children in config.yaml to allow more concurrent background units.r  r   r/   c                 óÎ  •— i } d}	  ‰¦   «         pi } |                       d¦  «        pg }|rt          d„ |D ¦   «         ¦  «        rd}nd}ns# t          $ rf}t                               d‰¦  «         g t          |¦  «        j        › d|› �t          t          j        ¦   «         ‰z
  d¦  «        dœ} d}Y d }~nd }~ww xY wt          ‰| |¦  «         d S # t          ‰| |¦  «         w xY w)	NrŠ   Úresultsc              3  óD   K  — | ]}|                      d ¦  «        dvV — ŒdS )r~   )r   ÚsuccessNrP   rÛ   s     r   rÝ   zCdispatch_async_delegation_batch.<locals>._worker.<locals>.<genexpr>  sF   è è € ð %ð %àð —’�x‘”Ð(@Ð@ð%ð %ð %ð %ð %ð %r   r   z!Async delegation batch %s crashedr   rÆ   ©rP  rŠ   Útotal_duration_seconds)
rQ   Úallr*   rµ   r#  r†   r$  r%  ra   Ú_finalize_batch)Úcombinedr~   Úchild_resultsr'  r[   r`   r  s       €€€r   r(  z0dispatch_async_delegation_batch.<locals>._workerú  s5  ø€ Ø#%ˆØˆð	=Ø�v‘x”x�~ 2ˆHà$ŸLšL¨Ñ3Ô3Ð9°rˆMØð %¥ð %ð %à&ð%ñ %ô %ñ "ô "ð %ð !��à$�øøÝð 	ð 	ð 	Ý×ÒÐ@À-ÑPÔPÐPàÝ  ™IœIÔ.Ð7Ð7°#Ð7Ð7Ý*/µ´	±´¸mÑ0KÈQÑ*OÔ*Oðð ˆHð
 ˆFˆFˆFˆFˆFˆFøøøøð	øøøõ ˜M¨8°VÑ<Ô<Ð<Ð<Ð<ø�O˜M¨8°VÑ<Ô<Ð<Ð<øøøs1   ‡AA Á
C Á
B;ÁAB6Â1C Â6B;Â;C ÃC$z+Failed to schedule async delegation batch: zADispatched async delegation batch %s (%d task(s), session_key=%s)r)  r+  r,  r-  )r÷   ra   rœ   Újoinrè   rß   rà   r   rá   rk   rÕ   r.  r   r*   r  ro   r/  rµ   r0  )rU   rV   rW   rX   rY   r\   r_   r  r^   r@   r  r  r[   r  ÚnÚcombined_goalrJ   rØ   r1  r(  r'  r`   s          `    `        @r   Údispatch_async_delegation_batchr\  ¤  sô  øøø€ ðJ "Ð9Õ%7Ñ%9Ô%9€MÝ”I‘K”K€MÝˆE‰
Œ
€Að ˜’F�FˆˆaŒˆ 1Ð ;Ð ;Ð ;¸d¿iºiÐG^ÐG^ÐX]ÐG^ÑG^ÔG^Ñ>^Ô>^Ñ ^ð ðØ˜ðà�ðð 	•�e‘”ðð 	�7ð	ð
 	 hÐ8•D˜‘N”N�N°Dðð 	�ðð 	�ðð 	�{ðð 	Ð 4ðð 	Ð.ðð 	Ð.ðð 	�)ðð 	˜ðð 	˜ðð 	˜ðð  	�Dð!ð" 	�{ð#ð$  Ø%Øð)ð ð €Fõ, 
ð )ð )Ýð 
ð 
Ý—’Ñ(Ô(ð
ñ 
ô 
ñ 
ô 
ˆð Ð(Ò(Ð(à$ðNÐ:Lð Nð Nð Nðð ð)ð )ð )ð )ñ )ô )ð )ð )ð #)��Ñð)ð )ð )ñ )ô )ð )ð )ð )ð )ð )ð )øøøð )ð )ð )ð )õ" �fÑÔÐÝÐ/Ñ0Ô0€Hð=ð =ð =ð =ð =ð =ð =ð =ð2

à�ŠÕ3°GÑ<Ô<Ñ=Ô=Ð=Ð=øÝð 
ð 
ð 
Ýð 	.ð 	.Ý�LŠL˜¨Ñ-Ô-Ð-ð	.ð 	.ð 	.ñ 	.ô 	.ð 	.ð 	.ð 	.ð 	.ð 	.ð 	.øøøð 	.ð 	.ð 	.ð 	.å" =Ñ1Ô1Ð1à ØHÀ3ÐHÐHð
ð 
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
øøøøð	
øøøð ÐÝÑÔÐå
‡K‚KØKØ�q˜+Ð0¨ñô ð ð #°]ÐCÐCÐCsZ   Ã	?D+Ä
D+Ä+D/Ä2D/Å"F  Æ 
G%Æ
G ÆF9Æ-G Æ9F=	Æ=G Ç F=	ÇG ÇG%Ç G%rW  c                óx   — t          | ¦  «        }|€dS |\  }}t          |||¦  «         t          | |¦  «         dS )zDMark a batch record complete and push ONE combined completion event.N)r4  Ú_push_batch_completion_eventr6  )r[   rW  r~   r7  r8  r9  s         r   rV  rV  (  sM   € õ " -Ñ0Ô0€GØ€ØˆØ")Ñ€L�-å  ¨x¸Ñ@Ô@Ð@Ý˜¨Ñ/Ô/Ð/Ð/Ð/r   r8  c                ó  — 	 ddl m} nG# t          $ r:}t                               d|                      d¦  «        |¦  «         Y d}~dS d}~ww xY w|                      d¦  «        pt          j        ¦   «         }|                      d¦  «        pt          j        ¦   «         }i dd	“d|                      d¦  «        “d
|                      d
d¦  «        “d|                      dd¦  «        “d|                      dd¦  «        “d|                      d¦  «        “d|                      dd¦  «        “d|                      d¦  «        “d|                      d¦  «        “d|                      d¦  «        “d|                      d¦  «        “d|                      d¦  «        “d|“dd“d|                     d¦  «        pg “d|                     d¦  «        “d|                     d¦  «        “|                     d¦  «        ||dœ¥}dD ]}||v r||         ||<   Œt          ||¦  «         	 |j         	                    |¦  «         dS # t          $ r:}t                               d|                      d¦  «        |¦  «         Y d}~dS d}~ww xY w)z8Push a combined async-delegation batch completion event.r   r>  zVAsync delegation batch %s finished but process_registry import failed; result lost: %sr[   Nr`   r€   r†   r‡   r\   r]   r^   r@   r_   rT   rU   rV   rW   rX   rY   r~   rZ   TrP  Úlive_transcriptsrŠ   rT  )rT  r`   r€   rA  zNAsync delegation batch %s: failed to enqueue completion event; result lost: %s)
rF  r?  r*   rµ   rŠ   rQ   ra   r�   rG  r›   )	r8  rW  r~   r?  r'  r`   r€   r    rH  s	            r   r^  r^  5  sC  € ðØ;Ð;Ð;Ð;Ð;Ð;Ð;øÝð ð ð Ý�Šð&à×Ò˜_Ñ-Ô-¨sñ	
ô 	
ð 	
ð
 	ˆˆˆˆˆøøøøðøøøð !×$Ò$ _Ñ5Ô5ÐD½¼¹¼€MØ×#Ò# NÑ3Ô3ÐBµt´y±{´{€LðØÐ"ðà˜×)Ò)¨/Ñ:Ô:ðð 	�|×'Ò'¨°rÑ:Ô:ðð 	 × 0Ò 0Ð1GÈÑ LÔ Lð	ð
 	˜\×-Ò-Ð.AÀ2ÑFÔFðð 	˜\×-Ò-Ð.AÑBÔBðð 	�× Ò  ¨Ñ,Ô,ðð 	�×!Ò! 'Ñ*Ô*ðð 	�<×#Ò# IÑ.Ô.ðð 	�L×$Ò$ ZÑ0Ô0ðð 	�× Ò  Ñ(Ô(ðð 	�×!Ò! 'Ñ*Ô*ðð 	�&ðð 	�Dðð" 	�8—<’< 	Ñ*Ô*Ð0¨bð#ð* 	˜HŸLšLÐ);Ñ<Ô<ð+ð, 	�—’˜gÑ&Ô&ð-ð. #+§,¢,Ð/GÑ"HÔ"HØ&Ø$ð3ð ð €Cð:ð #ð #ˆð �ˆ>ˆ>Ø˜r”lˆC�‰GøÝ˜˜XÑ&Ô&Ð&ð
ØÔ)×-Ò-¨cÑ2Ô2Ð2Ð2Ð2øÝð 
ð 
ð 
Ý�Šðà×Ò˜_Ñ-Ô-¨sñ	
ô 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
øøøøð
øøøs,   ‚	 ‰
A“/AÁAÈ#H? È?
JÉ	/I>É>Jc                 ó>  — t           5  t          �'t                               ¦   «         r	 ddd¦  «         dS t                               ¦   «          t          j        t          dd¬¦  «        at                               ¦   «          ddd¦  «         dS # 1 swxY w Y   dS )z÷Start (once) the module-level stale-delegation monitor thread.

    One daemon thread serves every dispatch; it exits on its own when no
    monitorable records remain, and is restarted by the next dispatch that
    carries a ``progress_fn``.
    Nzasync-delegate-stale-monitorT)ÚtargetrE   Údaemon)	Ú_monitor_lockr   Úis_aliveÚ_monitor_stopÚclearÚ	threadingÚThreadÚ_stale_monitor_loopÚstartr   r   r   r/  r/  u  sø   € õ 
ð 	 ð 	 ÝÐ&­?×+CÒ+CÑ+EÔ+EÐ&Øð	 ð 	 ð 	 ñ 	 ô 	 ð 	 ð 	 ð 	 õ 	×ÒÑÔÐÝ#Ô*Ý&Ø/Øð
ñ 
ô 
ˆõ
 	×ÒÑÔÐð	 ð 	 ð 	 ñ 	 ô 	 ð 	 ð 	 ð 	 ð 	 ð 	 ð 	 ð 	 øøøð 	 ð 	 ð 	 ð 	 ð 	 ð 	 s   ˆ"B·ABÂBÂBc            
     óú  — t                                t          ¦  «        �sÚt          j        ¦   «         } g }g }d}t          5  t
                               ¦   «         D �]}|                     d¦  «        }|dk    rCd}|                     d¦  «        p| }| |z
  t          k    r| 	                    |d         ¦  «         Œa|dk    rŒh|                     d¦  «        }|€Œ€d}	  |¦   «         \  }}	n'# t          $ r |                     d
¦  «        d}	}Y nw xY w||                     d
¦  «        k    r||d
<   | |d<   ŒÜ| |                     d¦  «        p| z
  }
|	rt          nt          }|
|k    rsd|d<   | |d<   t          |
d¦  «        |d<   ||d<   t          |	¦  «        |d<   | 	                    |d         t          |                     d¦  «        ¦  «        |
|	f¦  «         �Œ�	 d	d	d	¦  «         n# 1 swxY w Y   |D ]Ê\  }}}
}	t                               d||
|	t          ¦  «         t          5  t
                               |¦  «        }|r|                     d¦  «        nd	}d	d	d	¦  «         n# 1 swxY w Y   t#          |¦  «        r?	  |¦   «          Œ—# t          $ r&}t                               d||¦  «         Y d	}~ŒÂd	}~ww xY wŒË|D ]}t'          |¦  «         Œ|sd	S t                                t          ¦  «        �¯Ød	S d	S )uY  Sweep running delegations for stalled progress.

    Per sweep, for every running record with a ``progress_fn``:

    - Sample ``(token, in_tool)``. A changed token refreshes the record's
      progress timestamp â€” a child that keeps advancing is never touched, no
      matter how long it runs.
    - A frozen token past the idle/in-tool threshold marks the record
      ``stalling``: we call ``interrupt_fn`` so a responsive-but-slow child
      can unwind and deliver its (partial) result through the normal
      ``_finalize`` path with full fidelity.
    - A ``stalling`` record whose runner still hasn't returned after the
      grace window is force-finalized with one terminal ``stalled`` event so
      the owning session hears an outcome and the async slot frees. A late
      runner return after that is ignored by ``_begin_finalization``.
    Fr~   rÙ   Tr  r[   rØ   r  Nr  r  rÆ   Ú_stall_quiet_secondsÚ_stall_threshold_secondsÚ_stall_in_toolrZ   u`   Async delegation %s made no progress for %.0fs (in_tool=%s) â€” interrupting; grace window %.0fsr  z.Async delegation %s stall interrupt failed: %s)rf  ÚwaitÚ_STALE_CHECK_INTERVALra   rß   r   rá   rQ   Ú_STALL_GRACE_SECONDSÚappendr*   Ú_STALE_IN_TOOL_SECONDSÚ_STALE_IDLE_SECONDSr%  r�   rµ   r¶   ÚcallableÚdebugÚ_finalize_stalled)ri   ÚstalledÚexpiredÚany_monitorablerJ   r~   Úinterrupted_atr  ÚtokenÚin_toolÚ	quiet_forÚlimitr[   Ú	_is_batchÚfnr'  s                   r   rj  rj  ‰  sD  € õ" × Ò Õ!6Ñ7Ô7ñ HÝŒi‰kŒkˆØ!ˆØˆØˆÝð .	ð .	Ý"Ÿ/š/Ñ+Ô+ð -ñ -�ØŸš HÑ-Ô-�Ø˜ZÒ'Ð'Ø&*�OØ%+§Z¢ZÐ0AÑ%BÔ%BÐ%IÀc�NØ˜^Ñ+Õ/CÒCÐCØŸš v¨oÔ'>Ñ?Ô?Ð?ØØ˜YÒ&Ð&ØØ$Ÿjšj¨Ñ7Ô7�ØÐ&ØØ"&�ðJØ%0 [¡]¤]‘N�E˜7˜7øÝ ð Jð Jð Jð &,§Z¢ZÐ0AÑ%BÔ%BÀE˜7�E�E�EðJøøøð ˜FŸJšJÐ'8Ñ9Ô9Ò9Ð9Ø05�FÐ,Ñ-Ø-0�F˜>Ñ*ØØ 6§:¢:¨nÑ#=Ô#=Ð#DÀÑE�	à.5ÐNÕ*Ð*Õ;Nð ð  Ò%Ð%Ø'1�F˜8Ñ$Ø03�FÐ,Ñ-õ
 6;¸9ÀaÑ5HÔ5H�FÐ1Ñ2Ø9>�FÐ5Ñ6Ý/3°G©}¬}�FÐ+Ñ,Ø—N’Nà" ?Ô3Ý  §¢¨JÑ!7Ô!7Ñ8Ô8Ø%Ø#ð	ñô ð ùðM-ð.	ð .	ð .	ñ .	ô .	ð .	ð .	ð .	ð .	ð .	ð .	øøøð .	ð .	ð .	ð .	ð^ =Dð 	ð 	Ñ8ˆM˜9 i°Ý�NŠNðDà˜y¨'Õ3Gñô ð õ
 ð Dð DÝ!Ÿš mÑ4Ô4�Ø39ÐC�V—Z’Z Ñ/Ô/Ð/¸t�ðDð Dð Dñ Dô Dð Dð Dð Dð Dð Dð Døøøð Dð Dð Dð Dõ ˜‰|Œ|ð ðØ�B‘D”D�D�DøÝ ð ð ð Ý—L’LØHØ% sñô ð ð ð ð ð ð øøøøðøøøðð %ð 	-ð 	-ˆMÝ˜mÑ,Ô,Ð,Ð,Øð 	ØˆFõQ × Ò Õ!6Ñ7Ô7ñ Hð Hð Hð Hð Hsb   ÁBG)ÃC,Ã+G)Ã,!DÄG)ÄDÄCG)Ç)G-Ç0G-È'4I'É'I+	É.I+	Ê
JÊ
J=ÊJ8Ê8J=c           
     ón  — t          | ¦  «        }|€dS |\  }}|                     d¦  «        pt          j        ¦   «         }t          ||                     d¦  «        p|z
  d¦  «        }|                     d¦  «        }|                     d¦  «        }|                     d¦  «        }d| › d	�}	t                               d
| |¦  «         |||rdn|�dndt          dœ}
|                     d¦  «        rt          |g |	|dœ|
¥d¦  «         nt          |dd|	d|ddœ|
¥d¦  «         t          | d¦  «         dS )zAForce-finalize a stalling delegation whose runner never returned.Nr€   r`   rÆ   rm  rn  ro  zAsync delegation u^   stalled: the detached subagent stopped making progress (no new API calls, tool activity, or streamed tokens), did not respond to interruption, and never produced a completion event. The worker may be wedged inside a model API call â€” this is a known failure mode of long-lived gateway processes (#60203). Re-dispatch the task if it is still needed.z:Async delegation %s force-finalized as stalled after %.0fsr~  ÚidlerA  rZ   rS  ry  r   )r~   r‰   rŠ   r!  r"  r@  )
r4  rQ   ra   r%  rµ   rŠ   rr  r^  r5  r6  )r[   r7  r8  r9  r€   ÚdurationÚquiet_secondsÚthreshold_secondsÚstall_in_toolrŠ   Ú
stall_metas              r   rx  rx  å  sÆ  € å! -Ñ0Ô0€GØ€ØˆØ")Ñ€L�-à×#Ò# NÑ3Ô3ÐBµt´y±{´{€LÝØ˜×(Ò(¨Ñ9Ô9ÐI¸\ÑJØ	ñô €Hð !×$Ò$Ð%;Ñ<Ô<€MØ$×(Ò(Ð)CÑDÔDÐØ ×$Ò$Ð%5Ñ6Ô6€Mð	˜Mð 	ð 	ð 	ð 
õ ‡L‚LØDØ�xñô ð ð (5Ø#4à&ð ˆIˆIØ(Ð4��Øå3ð	ð 	€Jð ×Ò˜
Ñ#Ô#ð 
Ý$ØàØØ*2ðð ð ð	ð ñ		
ô 		
ð 		
ð 		
õ 	Øà#ØØØØ$,Ø(ðð ð ðð ñ	
ô 	
ð 	
õ ˜¨	Ñ2Ô2Ð2Ð2Ð2r   r}  r   ri   ÚfloatúOptional[List]c                ó  — 	 t          | ¦  «        }n# t          $ r Y dS w xY wg }|D ]Ù}t          |t           t          f¦  «        r¦t	          |¦  «        dk    r“|d         |d         dœ}t	          |¦  «        dk    rYt          |d         t
          t          f¦  «        r7t          t          d|t          |d         ¦  «        z
  ¦  «        d¦  «        |d<   | 	                    |¦  «         ŒÄ| 	                    d¦  «         ŒÚ|S )	ug  Parse a progress token into per-child activity dicts (best-effort).

    delegate_tool's ``_batch_progress`` emits one ``(api_call_count,
    current_tool, last_activity_ts)`` tuple per child. Foreign token shapes
    (custom dispatchers) degrade to ``None`` entries rather than raising â€”
    the token contract is intentionally opaque to the registry.
    NrÆ   r   r4   )r!  Úcurrent_toolr   g        Úseconds_since_activity)
rè   Ú	TypeErrorr™   ré   rœ   r   rŠ  r%  rs   rs  )r}  ri   ÚpartsÚoutÚpartÚentrys         r   Ú_children_activity_from_tokenr”  +  s  € ðÝ�U‘”ˆˆøÝð ð ð Øˆtˆtðøøøà*,€CØð ð ˆÝ�d�T¥5˜MÑ*Ô*ð 	­s°4©y¬y¸Aª~¨~à! !œWØ $ Q¤ð%ð %ˆEõ �4‰yŒy˜AŠ~ˆ~¥*¨T°!¬Wµs½E°lÑ"CÔ"Cˆ~Ý27Ý˜˜S¥5¨¨a¬¡>¤>Ñ1Ñ2Ô2°Añ3ô 3�Ð.Ñ/ð �JŠJ�uÑÔÐÐà�JŠJ�tÑÔÐÐØ€Js   ‚ ’
 Ÿ úList[Dict[str, Any]]c                 ó^  — t          j         ¦   «         } i }t          5  g }t                               ¦   «         D ]ã}d„ |                     ¦   «         D ¦   «         }|                     d¦  «        }|dv r\|                     d¦  «        }|rt          | |z
  d¦  «        |d<   |                     d¦  «        }t          |¦  «        r|||d         <   |d	v r5d
D ]2\  }}	|                     |¦  «        �|                     |¦  «        ||	<   Œ3|                     |¦  «         Œä	 ddd¦  «         n# 1 swxY w Y   |D ]u}|                     |                     d¦  «        ¦  «        }|€Œ-	  |¦   «         \  }
}n# t          $ r Y ŒHw xY wt          |
| ¦  «        }|�||d<   t          |¦  «        |d<   Œv|S )a—  Snapshot of async delegations (running + recently completed).

    Safe to call from any thread. Excludes the non-serialisable callables
    and private monitor bookkeeping, but exposes computed live-status
    fields for UIs (#51690):

    - ``seconds_since_progress``: how long the stale monitor has seen a
      frozen progress token (running/stalling records).
    - ``children_activity``: per-child ``{api_calls, current_tool,
      seconds_since_activity}`` sampled live from the dispatch's
      ``progress_fn``.
    - ``stalled_after_quiet_seconds`` / ``stall_threshold_seconds`` /
      ``stall_in_tool``: stall context once the monitor has tripped.
    c                óL   — i | ]!\  }}|d v¯	|                      d¦  «        °||“Œ"S )>   r  r  r  )Ú
startswith)r5   ÚkÚvs      r   rS   z*list_async_delegations.<locals>.<dictcomp>\  sH   € ð ð ð á�A�qØÐ;Ð;Ð;ØŸš SÑ)Ô)ð <ð �1à;Ð;Ð;r   r~   r  r  r4   Úseconds_since_progressr  r[   )rÙ   ry  ))rm  rB  )rn  rC  )ro  rˆ  NÚchildren_activityr~  )ra   rß   r   rá   rÿ   rQ   r%  rv  rs  r*   r”  r�   )ri   Úsamplersrÿ   rÜ   Úitemr~   Útsr‚  ÚsrcÚdstr}  r~  Úactivitys                r   Úlist_async_delegationsr£  H  s4  € õ Œ)‰+Œ+€CØ$&€HÝ	ð ð ØˆÝ—’Ñ"Ô"ð 	ð 	ˆAðð àŸGšG™IœIðñ ô ˆDð —U’U˜8‘_”_ˆFØÐ0Ð0Ð0Ø—U’U˜>Ñ*Ô*�Øð HÝ5:¸3À¹8ÀQÑ5GÔ5G�DÐ1Ñ2Ø—U’U˜=Ñ)Ô)�Ý˜B‘<”<ð 6Ø35�H˜Q˜Ô/Ñ0ØÐ0Ð0Ð0ð!ð /ð /‘H�C˜ð
 —u’u˜S‘z”zÐ-Ø$%§E¢E¨#¡J¤J˜˜S™	øØ�LŠL˜ÑÔÐÐð/	ðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ð< ð (ð (ˆØ�\Š\˜$Ÿ(š( ?Ñ3Ô3Ñ4Ô4ˆØˆ:Øð	Ø˜R™TœT‰NˆE�7�7øÝð 	ð 	ð 	ØˆHð	øøøå0°¸Ñ<Ô<ˆØÐØ(0ˆDÐ$Ñ%Ý˜w™-œ-ˆˆY‰ˆØ€Ls$   �D D*Ä*D.Ä1D.Å%E3Å3
F Å?F ÚshutdownÚreasonc                óÊ  — d}t           5  d„ t                               ¦   «         D ¦   «         }ddd¦  «         n# 1 swxY w Y   |D ]}}|                     d¦  «        }t	          |¦  «        rW	  |¦   «          |dz  }Œ7# t
          $ r9}t                               d|                     d¦  «        |¦  «         Y d}~Œud}~ww xY wŒ~|rt                               d|| ¦  «         |S )	a*  Signal every running async delegation to stop. Returns how many.

    Used on ``/stop`` and gateway shutdown so a dangling background subagent
    can't keep burning tokens with no one listening. The child still emits a
    completion event (status='interrupted') via the normal finalize path.
    r   c                ó@   — g | ]}|                      d ¦  «        dv ¯|‘ŒS )r~   r  rP   rÛ   s     r   rû   z!interrupt_all.<locals>.<listcomp>�  s8   € ð 
ð 
ð 
ØØ�uŠu�X‰ŒÐ"9Ð9Ð9ð Ø9Ð9Ð9r   Nr  r4   z&interrupt_all: %s interrupt failed: %sr[   z'Interrupted %d async delegation(s) (%s)©	rß   r   rá   rQ   rv  r*   rµ   rw  r0  )r¥  ÚcountÚtargetsrÜ   r‚  r'  s         r   Úinterrupt_allr«  †  se  € ð €EÝ	ð 
ð 
ð
ð 
Ý—’Ñ(Ô(ð
ñ 
ô 
ˆð
ð 
ð 
ñ 
ô 
ð 
ð 
ð 
ð 
ð 
ð 
øøøð 
ð 
ð 
ð 
ð
 ð 
ð 
ˆØ�UŠU�>Ñ"Ô"ˆÝ�B‰<Œ<ð 	ðØ�‘”�Ø˜‘
��øÝð ð ð Ý—’Ø<Ø—E’E˜/Ñ*Ô*¨Cñô ð ð ð ð ð ð øøøøðøøøð		ð ð NÝ�ŠÐ=¸uÀfÑMÔMÐMØ€Ls%   Š$:º>Á>Á.A>Á>
CÂ/B<Â<CÚsession_endc                óè  ‡ ‡‡— ‰ s‰s‰sdS d}t           5  ˆˆˆ fd„t                               ¦   «         D ¦   «         }ddd¦  «         n# 1 swxY w Y   |D ]}}|                     d¦  «        }t	          |¦  «        rW	  |¦   «          |dz  }Œ7# t
          $ r9}t                               d|                     d¦  «        |¦  «         Y d}~Œud}~ww xY wŒ~|rt                               d||¦  «         |S )	u{  Signal running async delegations owned by ONE session to stop.

    A delegation's lifecycle is bound to the session that spawned it: when
    that session ends, its in-flight background subagents must end with it â€”
    a completed orphan would otherwise sit on the shared completion queue
    with no live owner, either leaking into another chat or burning tokens
    with no one listening (#55578).

    Selectors (any matching field claims the record):
    - ``origin_ui_session_id``: the live TUI tab/window that commissioned it.
    - ``session_key``: the durable routing key captured at dispatch.
    - ``parent_session_id``: the spawning agent's durable session-db id â€”
      the right selector for gateway chats, whose ``session_key`` (the
      platform conversation key) SURVIVES a ``/new`` reset while the
      session id rotates.

    Returns how many were interrupted.
    r   c                óh   •— g | ].}|                      d ¦  «        dv ¯t          |‰‰‰¬¦  «        ¯,|‘Œ/S )r~   r  rì   rñ   rò   s     €€€r   rû   z)interrupt_for_session.<locals>.<listcomp>¿  s\   ø€ ð 	
ð 	
ð 	
ØØ�uŠu�X‰ŒÐ"9Ð9Ð9Ý*ØØ'Ø%9Ø"3ð	ñ ô ð :ð Ø9Ð9Ð9r   Nr  r4   z.interrupt_for_session: %s interrupt failed: %sr[   z:Interrupted %d async delegation(s) for ending session (%s)r¨  )	r\   r^   r_   r¥  r©  rª  rÜ   r‚  r'  s	   ```      r   Úinterrupt_for_sessionr¯  £  s¡  øøø€ ð0 ð Ð3ð Ð<Mð ØˆqØ€EÝ	ð 

ð 

ð	
ð 	
ð 	
ð 	
ð 	
ð 	
Ý—’Ñ(Ô(ð	
ñ 	
ô 	
ˆð

ð 

ð 

ñ 

ô 

ð 

ð 

ð 

ð 

ð 

ð 

øøøð 

ð 

ð 

ð 

ð ð 
ð 
ˆØ�UŠU�>Ñ"Ô"ˆÝ�B‰<Œ<ð 	ðØ�‘”�Ø˜‘
��øÝð ð ð Ý—’ØDØ—E’E˜/Ñ*Ô*¨Cñô ð ð ð ð ð ð øøøøðøøøð		ð ð 
Ý�ŠØHØ�6ñ	
ô 	
ð 	
ð €Ls)   •(A	Á	AÁAÁ=BÂ
CÂ/CÃCc                 óÜ  — t           5  t          �t                               d¬¦  «         dadaddd¦  «         n# 1 swxY w Y   t                               ¦   «          t          5  t          } daddd¦  «         n# 1 swxY w Y   | �*|                      ¦   «         r|  	                    d¬¦  «         t          5  t                               ¦   «          ddd¦  «         dS # 1 swxY w Y   dS )z@Test-only: clear all state and tear down the executor + monitor.NF)rp  r   rÆ   r#   )rÓ   r   r¤  r   rf  Úsetrd  r   re  rY  rß   r   rg  )Úthreads    r   Ú_reset_for_testsr³  Ü  s¥  € õ 
ð "ð "ÝÐ Ý×Ò EÐÑ*Ô*Ð*Øˆ	Ø !Ðð	"ð "ð "ñ "ô "ð "ð "ð "ð "ð "ð "øøøð "ð "ð "ð "õ
 ×ÒÑÔÐÝ	ð ð Ý ˆØˆðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ð Ð˜fŸošoÑ/Ô/ÐØ�Š˜AˆÑÔÐÝ	ð ð Ý�ŠÑÔÐðð ð ñ ô ð ð ð ð ð ð ð øøøð ð ð ð ð ð s1   ˆ';»?Á?Á&
A<Á<B ÂB Â:C!Ã!C%Ã(C%)r   r   )r-   r   r   r/   )r   rG   )rJ   rK   r   r/   )r[   rl   r   r/   r-  )r{   rK   r|   rK   r   r/   )r   r   )r[   rl   r   r�   )r[   rl   r¨   rl   r   r�   )r    rK   r«   rl   r   r¬   )r    rK   r¨   rl   r   r/   )r[   rl   r   rÄ   )rÐ   r   r   r   )r^   rl   r   r   )
rJ   rK   r\   rl   r^   rl   r_   rl   r   r�   )r]   r]   r]   )r\   rl   r^   rl   r_   rl   r   r�   )r   rl   )rT   rl   rV   r¬   rW   r  rX   rl   rY   r¬   r\   rl   r_   r¬   r  r  r^   rl   r@   rl   r  r  r  r   r  r  r   rK   )r[   rl   r|   rK   r~   rl   r   r/   )r[   rl   r   r:  )r[   rl   r~   rl   r   r/   )rJ   rK   r|   rK   r~   rl   r   r/   )rU   rI  rV   r¬   rW   r  rX   rl   rY   r¬   r\   rl   r_   r¬   r  r  r^   rl   r@   rl   r  r  r  r   r[   r¬   r  r  r   rK   )r[   rl   rW  rK   r~   rl   r   r/   )r8  rK   rW  rK   r~   rl   r   r/   )r}  r   ri   rŠ  r   r‹  )r   r•  )r¤  )r¥  rl   r   r   )r]   r]   r]   r¬  )
r\   rl   r^   rl   r_   rl   r¥  rl   r   r   )`Ú__doc__Ú
__future__r   rf   Úloggingr'   rh  ra   r¯   Úconcurrent.futuresr   Ú
contextlibr   Útypingr   r   r   r	   r
   r   Úhermes_constantsr   Útools.daemon_poolr   Útools.thread_contextr   Ú	getLoggerr$  rµ   rÔ   r   Ú__annotations__ÚLockrÓ   r   rß   r   Ú_DEFAULT_MAX_ASYNC_CHILDRENrt   rq   ru   r´   re   rq  ru  rt  rr  rd  r   ÚEventrf  r   r.   r)   rI   rk   ro   rh   r�   rƒ   r–   r¡   r¦   rª   r²   r¸   r»   r½   rÁ   rÃ   rÏ   rÕ   râ   ræ   rë   rî   rô   r÷   r  r  r2  r&  r4  r6  r5  r\  rV  r^  r/  rj  rx  r”  r£  r«  r¯  r³  r   r   r   ú<module>rÂ     s*  ðð!ð !ð !ðF #Ð "Ð "Ð "Ð "Ð "à €€€Ø €€€Ø €€€Ø Ð Ð Ð Ø €€€Ø €€€Ø 1Ð 1Ð 1Ð 1Ð 1Ð 1Ø %Ð %Ð %Ð %Ð %Ð %Ø @Ð @Ð @Ð @Ð @Ð @Ð @Ð @Ð @Ð @Ð @Ð @Ð @Ð @Ð @Ð @à ,Ð ,Ð ,Ð ,Ð ,Ð ,Ø 6Ð 6Ð 6Ð 6Ð 6Ð 6Ø <Ð <Ð <Ð <Ð <Ð <à	ˆÔ	˜8Ñ	$Ô	$€ð
 5Ð ð +/€	Ð .Ð .Ð .Ñ .Ø�”Ñ!Ô!€ØÐ Ð Ð Ð Ñ à�	”Ñ Ô €ð ')€Ð (Ð (Ð (Ñ (àÐ àÐ Ø-Ð ØÐ ð
 Ð Øˆ9Œ>ÑÔ€ð. Ð ØÐ ØÐ ØÐ à�	”Ñ Ô €Ø.2€Ð 2Ð 2Ð 2Ñ 2Ø�	”Ñ!Ô!€ð*ð *ð *ðð ð ð ð)Xð )Xð )Xð )XðX ðð ð ñ „ðð$ð ð ð ð:^ð ^ð ^ð ^ð
$ð $ð $ð $ðN	
ð 	
ð 	
ð 	
ð
ð 
ð 
ð 
ð0ð 0ð 0ð 0ðfð ð ð ð6	!ð 	!ð 	!ð 	!ð!ð !ð !ð !ð(Tð Tð Tð Tð!!ð !!ð !!ð !!ðH!ð !ð !ð !ð,!ð !ð !ð !ðTð Tð Tð Tð
Sð Sð Sð Sð
ð ð ð ð&ð ð ð ð&
ð 
ð 
ð 
ð 
ð 
ð 
ð 
ðð ð ð ð4 Ø "Øðð ð ð ð ð ð Ø "Øð
ð 
ð 
ð 
ð 
ð2+ð +ð +ð +ð ð  ð  ð  ð$ð ð ð ðH (,à "ØØ15Ø9Ø15ðODð ODð ODð ODð ODð ODðd0ð 0ð 0ð 0ð&ð &ð &ð &ð*"ð "ð "ð "ðB
ð B
ð B
ð B
ðZ (,à "ØØ15Ø9Ø#'Ø15ðADð ADð ADð ADð ADð ADðH
0ð 
0ð 
0ð 
0ð=
ð =
ð =
ð =
ð@ ð  ð  ð  ð(Yð Yð Yð YðxC3ð C3ð C3ð C3ðLð ð ð ð:;ð ;ð ;ð ;ð|ð ð ð ð ð< Ø "ØØð	6ð 6ð 6ð 6ð 6ðrð ð ð ð ð r   