Skip to content

fix(tools): settle ToolRunner completion after early iterator return - #1205

Draft
rioyu123 wants to merge 1 commit into
anthropics:mainfrom
rioyu123:fix/toolrunner-early-completion
Draft

rioyu123 wants to merge 1 commit into
anthropics:mainfrom
rioyu123:fix/toolrunner-early-completion

Conversation

@rioyu123

Copy link
Copy Markdown

Summary

Returning early from BetaToolRunner's iterator skips both its normal completion handler and its error handler. As a result, done() can keep waiting after the iterator has returned; runUntilDone() and directly awaiting the runner also wait on that same unfinished completion promise.

This draft proposes rejecting completion with an AnthropicError when an iterator that has started is closed early. It does not run pending tools, start another request, or return a message as though the conversation completed normally. The existing stream-abort path and the error path that lets the runner be iterated again after a failed request stay unchanged.

Behavior to confirm

Is rejecting completion the desired behavior for an early break or iterator.return()? The proposed rule also applies when the last yielded message has stop_reason: 'end_turn', because the iterator was closed before its normal completion path ran. Closing an iterator before its first next() leaves the runner unconsumed.

Callers waiting for completion after an early stop would need to handle this rejection. For example, a runner.done().then(onSuccess) chain with no rejection handler would now reject rather than remain pending. Breaking without observing completion still does not produce an unhandled rejection from the runner itself.

I am keeping this as a draft until that completion behavior is agreed.

Test plan

  • Added five cases to the existing ToolRunner test suite: pending-tool early return, breaking on a final message, streaming early return, consumer errors, and return before iteration starts. Four fail on the unchanged base; the never-started control already passes.
  • The tests use the public SDK runner and the repository's mock fetch/SSE fixtures. They check completion settlement, preservation of the consumer error, no pending-tool dispatch, the existing stream abort, and late completion waiters. The tests make no live API calls and make no claims about connection cleanup.
  • Focused ToolRunner suite: 82 passed.
  • Linux / Node 22: pnpm build, pnpm lint, and pnpm test passed. Across the main SDK and five subpackages: 2,033 tests passed, 60 skipped. Tests used the repository's local Steady mock server.
  • git diff --check passed.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant