Preserve cancellation across AI, MCP and telemetry integrations
Cancellation could be mistaken for an ordinary failure when AI callbacks, MCP transports or telemetry hooks threw during cleanup. That could trigger retries, send error responses or continue recording after the operation had been canceled.
Preserve cancellation at the existing integration boundaries:
- Keep AI failure observers and conversation persistence from replacing cancellation; preserve child-task ownership and completed-turn fallback behavior.
- Stop MCP handshake retries and server error responses when cancellation is wrapped by cleanup, while still closing owned transports.
- Propagate cancellation from OpenTelemetry, Sentry and Telescope callbacks without hiding genuine ordinary failures or skipping required cleanup.
Regression coverage checks direct and wrapped cancellation, callback failures, transport cleanup and ordinary-error behavior. Targeted source analysis and affected tests pass. The full suite and service matrices run in CI.
Summary by cubic
Cancellation was previously mistaken for an ordinary failure when AI callbacks, MCP transports, or telemetry hooks threw during cleanup. That could trigger retries, send error responses, or continue recording after the operation had been canceled.
Cancellation is now preserved at integration boundaries by using Coroutine::causedByCancellation and preferCancellation instead of referring to Swoole\Coroutine\CanceledException directly.
- AI failure observers, step/tool reporters, and stream catch callbacks now run from
finally, keeping the original cancellation alive even when reporting throws. Independently canceled concurrent tools and title generation surface asChildCancellationExceptionwithout discarding completed turns. - MCP handshake fallback no longer retries after cancellation, server handlers no longer convert cancellation into error responses or empty completions, and transport cleanup prefers cancellation while still closing owned sessions.
- OpenTelemetry, Sentry, and Telescope fallback catches now rethrow cancellation chains before applying their ordinary-error handling, so canceled operations stop telemetry recording exactly where they should.
Regression tests cover direct and wrapped cancellation, throwing callbacks, transport cleanup, and ordinary-error behavior across the affected integrations.
[!NOTE]
Preserve cancellation across AI, MCP and telemetry integrations
- Replaces direct
CanceledException type checks with Coroutine::causedByCancellation and Coroutine::preferCancellation across OpenTelemetry, Sentry, Telescope and MCP instrumentation, so cancellations wrapped in other exceptions propagate instead of being logged or converted to fallback values
- Reworks AI failure-reporting paths (
RememberConversation, GeneratesText, StreamsText, TextGenerationLoop, InvokesTools, Provider.dispatchingFailure, StreamableAgentResponse) to throw the original exception first and run reporting in finally, so a reporting failure retains the original as its previous exception
- Cancellation-caused tool failures and title-generation failures are now stored as
ChildCancellationException with the caught exception as previous
- MCP
Server.sendException and response handling now rethrow cancellation-caused exceptions instead of converting them to JSON-RPC errors; ClientManager and transport cleanup paths give cancellation precedence over other failures
- Risk: behavioral change — places that previously swallowed or logged failures (e.g.
JsonNormalizer.normalize, DumpWatcher::shouldRecordDump, Telescope Auth/cache lookups, Hub::startTransaction samplers) now rethrow any throwable whose cause chain contains a cancellation; non-cancellation failures keep prior behavior
Macroscope summarized 9f7e35e.
Summary by CodeRabbit
- Bug Fixes
- Coroutine cancellation is now preserved across AI generation, tool execution, conversation storage, MCP requests, and telemetry integrations—even when wrapped by another exception.
- Failure reporting and cleanup are less likely to obscure the original error or cancellation.
- Completed conversation turns remain saved when title generation is canceled, and canceled operations are no longer silently treated as ordinary failures.
- Tests
- Expanded coverage for direct and wrapped cancellations, cleanup failures, and exception handling.