Plugins get a new turn object whose abort verb ends the running turn with its own interrupt wording.
What's wrong with this entry?
Plugin function hooks can now end the turn in progress through a new turn object on the plugin API surface, sitting alongside the existing tool, agent, fs, store and clock objects. Any tool call still running when the abort lands comes back as the synthetic result "[Request interrupted by a plugin for tool use]", which is distinct from the wording used when a person rejects a tool. Its only verb is abort, and it needs the turn id that the plugin was handed when the turn began.
turn.startnow carries a turn id and an abort callback, and a hook passes that id back as$.turn.abort({ turnId }); calling it without the id rejects with an error.- The interrupted tool result is recorded with denial kind
interrupted, not the user-rejected kind. - The turn's controller is aborted with a new cancellation reason,
turn-abort, which is included in the sets that treat an interruption as user-initiated. - Misuse produces
$.turn.abort: no turn is runningor$.turn.abort: <id> is already ending. - Rate limited to one abort per 2000ms per plugin and 50 aborts per session.
- The
turnobject is registered unconditionally for any plugin using function hooks, with no feature gate around it; a separate helper restricts a differently named object,flag, to internal builds only, so that one is present but off in this build.
[Request interrupted by a plugin for tool use], $.turn.abort takes { turnId } (the id turn.start carried)
Strings lifted out of the shipped bundle, so the claim above can be checked against them.