Repository navigation
Conversation
…he round (DEV-1067) Co-authored-by: Cursor <cursoragent@cursor.com>
…-call Resolve the conflict with #110 (drop preliminaryResults): remove preliminaryResultsForCall from SingleToolCallOutcome and the broadcastToolResult call, and make SingleToolCallOutcome non-generic. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ms by call - executeToolRound awaits Promise.allSettled over the per-call finalizers and rethrows the first rejection in call order. Promise.all rejected the round as soon as one call's toModelOutput threw, orphaning still-running siblings (late broadcasts dropped, async calls registering after the run failed). - ctx.defer() registration waits on earlier calls' claim gates so rejectDuplicateTaskId picks the earlier call deterministically, as it did before per-call finalization. Only deferred calls wait. - Regression tests for both; changeset calls out completion-order events. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Contributor
|
Pushed 2 commits:
|
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary, root cause, and test plan (AGENT-WRITTEN)
Fixes DEV-1067
Problem
When a model emits multiple tool calls in one turn,
executeToolRoundawaitedPromise.allSettledover the entire round before broadcasting anytool.result/tool.call_outputevents. With serial execution (maxConcurrency: 1), an early call could be finished for minutes while its chip in the chatroom still showed "Running...", and then every chip flipped to completed at once when the last call finished.Change
executeToolRoundnow attaches a settle-time finalizer to each tool-call promise (finalizeSettledRoundCall/finalizeRejectedRoundCall): thetool.result, legacytool_result, andtool.call_outputbroadcasts — andcomputeToolOutputForModel— run the moment that call settles.Promise.allSettled, an ordered loop collects the pre-finalizedfunction_call_outputs in call order, so the follow-up request input and prompt-cache behavior are byte-identical.allSettledparallel kickoff, so no(N-1)×graceMsstagger is reintroduced.executeSingleToolCalloutcome union into a namedSingleToolCallOutcometype and added apushToolCallOutputEventhelper (the push was previously duplicated at four sites).Behavior notes
tool.call_output/tool.result/ legacytool_resultevents on the wire are now emitted in completion order (previously call order); the changeset calls this out.tool.resultevents were already only meaningful per call. The model-facingfunction_call_outputarray order is unchanged.computeToolOutputForModel(toModelOutput) throws for one call,executeToolRoundwaits for every sibling call to settle (Promise.allSettledover the finalizers) and then rejects with the first error in call order. Siblings' broadcasts and async registrations all land before the run fails. (Edit: an earlier revision usedPromise.allhere, which rejected immediately and orphaned still-running siblings.)ctx.defer()taskId collisions within a round are still resolved in call order (the earlier call wins). A deferred call's registration waits for earlier calls in the round to settle; other calls are unaffected.Tests
New
tests/unit/tool-round-settle-broadcast.test.ts:tool.result+tool.call_outputappear on the turn broadcaster while a slow sibling in the same round is still gated, and the follow-up request'sfunction_call_outputs stay in call order (slow first) despite settling second.Full suite: 103 files / 1219 tests pass; lint and typecheck clean.
Release
Changeset included (patch). Follow-up after release: bump
@openrouter/agentin openrouter-web (the existingpatches/@openrouter%2Fagent@0.10.0.patchthere will need re-basing onto the new version).Made with Cursor