The timeout is carried to the plugin-daemon transport through a ContextVar
(core.plugin.impl.first_token_timeout) and applied as httpx's per-request
read timeout in BasePluginClient._stream_request. The daemon withholds the
response headers until the model's first token, so the read timeout measures
time-to-first-token directly; a ReadTimeout before the first line surfaces as
FirstTokenTimeoutError (dify-local, subclassing graphon's InvokeError), while
a later stall stays a plain transport error. A non-positive budget disables
the gate.