SIGN IN SIGN UP

fix(security): stop delayed and additional tool callbacks after cancellation (#2430)

## Summary

- Prevent `chat.completions.runTools()` from starting a privileged
parsed tool callback after cancellation occurs during asynchronous
argument parsing.
- Prevent cancellation from starting the next sequential or later
parallel tool callback, for both non-streaming and streaming runners and
both external abort signals and `runner.abort()`.
- Surface the existing public `APIUserAbortError`, wait for callbacks
that were already running, and retain results/messages for callbacks
that began before cancellation.
- Preserve the SDK's documented completed-buffered-turn compatibility
contract: when a completed response is already buffered as cancellation
becomes visible, its **first immediate, non-parsing callback may still
run**. This exception is consumed once, never permits an asynchronously
parsed callback, and never permits a second callback.

## Regression-first proof

Before the change, the new real-public-client suite produced **10
failing security cases and 6 passing compatibility controls**: synthetic
privileged transfer callbacks ran with the runner signal already
aborted. The final **20-case** suite covers non-streaming and streaming
public clients, external abort signals and direct runner cancellation,
delayed parsers, sequential callbacks, in-flight parallel callback
completion, one-shot buffered-turn compatibility, context, parser
feedback, and `afterCompletion`.

## Verification

- Focused public runner coverage: **58 tests passed** (20 new
security/compatibility cases plus all 38 existing runner cases).
- Complete handwritten suite: **127 files / 4,064 tests passed**.
- Complete generated suite against an isolated private-port Steady
server: **82 suites / 559 tests passed**.
- Repository formatting and all **415 lint rules** passed.
- Strict source TypeScript checking and the complete CJS/ESM package
build passed.
- Published-source type checking passed with **TypeScript 4.9 and
TypeScript 6**.
- `publint` passed with only the pre-existing vendor-export warning.
- Packed artifact checks passed across **1,216 source maps and 267
browser-safe mapped sources**.
- Built-distribution public smoke checks passed for non-streaming and
streaming runners, covering both delayed parsing and cancellation
between sequential callbacks.
H
Hayden committed
c1685991da6dca1e0813ef25a3b584565278c621
Parent: 01a15bd
Committed by GitHub <noreply@github.com> on 8/24/2026, 5:34:21 PM