Address the two non-blocking follow-ups from review:
- next_call is now single-use per middleware frame. A second invocation
raises instead of silently re-running the downstream provider/tool, so
the terminal call cannot execute twice via the chain. The error surfaces
through the existing handler, which preserves the first downstream result.
- Request-middleware payload copies go through _safe_copy(), which falls
back to a shallow dict copy when deepcopy() fails on a non-deepcopyable
member (clients, callbacks, file handles) instead of aborting the pass.
Adds regression coverage for both: double next_call() keeps the terminal
single-run, and a non-deepcopyable (threading.Lock) request payload still
runs middleware via the shallow fallback.
Track successful next_call completion separately from invocation so execution
middleware that catches and translates a downstream provider/tool failure does
not accidentally convert that failure into a successful None result.
Also avoid wrapping BaseException from downstream execution, and document the
execution middleware error semantics.
Tests cover:
- pre-next_call middleware failures fail open to the remaining chain
- post-next_call middleware failures preserve the downstream result
- translated downstream failures propagate instead of returning None
- downstream BaseException is not wrapped
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>