§
    ˜è[jJ  ã                  óZ   — d Z ddlmZ ddlZddlmZ  ej        e¦  «        Zdd	„Z	dd„Z
dS )u®  Best-effort accessors for the single-writer stream fence (#65991).

The fence itself lives on ``AIAgent`` (``_claim_stream_writer`` /
``_stream_writer_is_current`` in ``run_agent.py``), but the streaming code paths
that use it live in *other* modules â€” ``chat_completion_helpers`` (chat /
anthropic / bedrock) and ``codex_runtime`` (codex responses). Calling the fence
directly as ``agent._claim_stream_writer()`` from those modules makes them
hard-depend on the method being present on whatever object is passed in as
``agent``.

That coupling is a latent crash: a partially-updated checkout (the streaming
helper module newer than ``run_agent``), a hot-reloaded gateway, a duck-typed
agent, or a test double without the method turns an *additive* safety net into a
fatal ``AttributeError`` that aborts the whole turn. A cron job died exactly
this way with ``'AIAgent' object has no attribute '_claim_stream_writer'``.

The fence is only ever allowed to drop a *provably* superseded stream â€” never
the sole legitimate writer. So when the guard is unavailable (or raises), the
correct degradation is "no fence": keep streaming. These helpers make the
claim/check best-effort to guarantee that.
é    )ÚannotationsN)ÚAnyÚagentr   ÚreturnÚintc                óÎ   — t          | dd¦  «        }t          |¦  «        rD	 t           |¦   «         ¦  «        S # t          $ r t                               dd¬¦  «         Y nw xY wdS )a€  Claim the delta sink for the calling stream attempt, best-effort.

    Returns the agent's monotonic writer token when the fence is available, or
    ``0`` when the agent doesn't expose it (or the claim raised). A ``0`` token
    pairs with :func:`stream_writer_is_current` always returning ``True``, so a
    guard-less agent is simply never fenced instead of crashing the turn.
    Ú_claim_stream_writerNz7stream single-writer: claim failed; proceeding unfencedT©Úexc_infor   )ÚgetattrÚcallabler   Ú	ExceptionÚloggerÚdebug)r   Úclaims     ú</home/ice/.hermes/hermes-agent/agent/stream_single_writer.pyÚclaim_stream_writerr      sˆ   € õ EÐ1°4Ñ8Ô8€EÝ„ð ð	Ýuu‘w”w‘<”<ÐøÝð 	ð 	ð 	ÝLŠLØIØð ñ ô ð ð ð ð	øøøð
 ˆ1s   ¢9 ¹&A"Á!A"ÚtokenÚboolc                óØ   — |sdS t          | dd¦  «        }t          |¦  «        rE	 t           ||¦  «        ¦  «        S # t          $ r t                               dd¬¦  «         Y nw xY wdS )ad  True when ``token`` is still the active writer, best-effort.

    A falsy token (from a claim that no-oped) or an agent without the fence
    means we cannot prove supersession, so the stream is treated as current and
    never fenced. This preserves the single-writer invariant's one-way promise:
    only a demonstrably stale writer is ever stopped.
    TÚ_stream_writer_is_currentNzBstream single-writer: is_current check failed; treating as currentr
   )r   r   r   r   r   r   )r   r   Ú
is_currents      r   Ústream_writer_is_currentr   3   s   € ð ð ØˆtÝ˜Ð ;¸TÑBÔB€JÝ
ÑÔð ð	Ý˜
˜
 5Ñ)Ô)Ñ*Ô*Ð*øÝð 	ð 	ð 	ÝLŠLØTØð ñ ô ð ð ð ð	øøøð
 ˆ4s   ¦> ¾&A'Á&A')r   r   r   r   )r   r   r   r   r   r   )Ú__doc__Ú
__future__r   ÚloggingÚtypingr   Ú	getLoggerÚ__name__r   r   r   © ó    r   ú<module>r"      s‚   ððð ð, #Ð "Ð "Ð "Ð "Ð "à €€€Ø Ð Ð Ð Ð Ð à	ˆÔ	˜8Ñ	$Ô	$€ðð ð ð ð(ð ð ð ð ð r!   