c5b99a3ee5
should_use_direct_api_call() contexts (gateway cron turns #62151, delegate_task children #60203) were short-circuited onto the NON-streaming wire because the interrupt worker wedges inside their nested thread pools. That dropped every liveness property streaming provides: edge proxies kill the silent POST (z.ai HTTP 524 — three retries later the child dies as "max_iterations"), and the non-stream stale watchdog cannot tell a reasoning model's thinking phase from a hung provider, so children die at exactly stale_timeout (#100260). Keep those contexts on interruptible_streaming_api_call. The request now runs INLINE on the conversation thread (no worker → the deadlock class stays closed) while the existing poll loop — 30s heartbeat, stale-stream detector, cross-thread interrupt abort — moves onto a monitor thread that only ever aborts sockets, never dispatches (same shape as direct_api_call's watchdog timer). Interactive sessions are unchanged: worker + poll loop as before. should_use_direct_api_call() itself is untouched; only what it routes to. Live A/B (real SSE server, real AIAgent.run_conversation): before: subagent/cron wire stream=None, request on conversation thread after: subagent/cron wire stream=True, request on conversation thread cli unchanged (stream=True, spawned worker) inline stale detector kills a one-chunk-then-silence stream at budget; AIAgent.interrupt() from another thread unwinds the inline stream in 0.6s. Co-authored-by: Expri-commits <184641533+Expri-commits@users.noreply.github.com>