Repository navigation
SEC-768: fix(agent): check stopWhen before running auto-approved siblings of an approval-gated call - #143
Merged
alexb-openrouter merged 1 commit intoNov 5, 2026
Conversation
…n approval-gated call Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Contributor
|
I'll fix CI failures and address comments from users with write access that start with 'Devin'.
|
talos
approved these changes
Nov 5, 2026
Merged
LukasParke
added a commit
to OpenRouterTeam/typescript-sdk
that referenced
this pull request
Nov 5, 2026
…outer/agent (#1356) ## Summary SEC-768 (`stopWhen` checked after auto-approved siblings of an approval-gated call ran) is in the SDK's old copy of `callModel`. `callModel` and its tool system moved to `@openrouter/agent` (see the README's migration note), and the copy here is not exported from the package entry points. So this PR deletes that code instead of fixing it. The agent-side fix is OpenRouterTeam/typescript-agent#143. Removed: - `src/funcs/call-model.ts` and the 19 hand-written `src/lib/` files that only it used: `model-result`, `tool`, `tool-types`, `tool-executor`, `tool-orchestrator`, `tool-context`, `tool-event-broadcaster`, `conversation-state`, `stop-conditions`, `next-turn-params`, `async-params`, `turn-context`, `reusable-stream`, `stream-transformers`, `stream-type-guards`, `anthropic-compat`, `chat-compat`, `claude-type-guards`, `claude-constants`. No generated file imports any of them. - The `OpenRouter#callModel` method and the `ToolType` re-export in the custom regions of `src/sdk/sdk.ts`. - The 11 unit tests and 5 examples that used this code. Also removed the `callModel` architecture section from `CLAUDE.md`. Breaking-change note: `OpenRouter#callModel` and `ToolType` were still on the class and in the 1.5.56 typings. `Tool`, `tool()`, stop conditions and `ModelResult` were not exported from any entry point. Anyone who still calls `client.callModel()` must move to `@openrouter/agent`. ## Testing - `pnpm run lint`, `pnpm run typecheck`, `pnpm run build` pass. `esm/sdk/sdk.d.ts` no longer mentions `callModel`. - `pnpm test`: 7 files, 65 tests pass. - CI `validate` has been failing on the live-API e2e test `tests/e2e/image-generation.test.ts`. The same failure shows up on other open PRs, so this change didn't cause it. Fixes SEC-768 Link to Devin session: https://openrouter.devinenterprise.com/sessions/c1a6389d6666493e86069406d08ef2ef Open in Devin Desktop: https://openrouter.devinenterprise.com/desktop/session/c1a6389d6666493e86069406d08ef2ef?variant=devin Requested by: @alexb-openrouter --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Luke Parke <5702154+LukasParke@users.noreply.github.com>
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.
The risk in plain terms
stopWhenthat is already true andallowFinalResponse: false, meaning "do not run any tools". If the model's first response contains one auto-executable tool call plus one call that needs approval, the agent runs the auto-executable tool once before it checksstopWhen.stopWhenthis way are affected.How this PR fixes it
On the first response,
ModelResultnow evaluatesshouldStopExecution()beforehandleApprovalCheck()whenallowFinalResponse === false, and passes the result in. When it is met,handleApprovalCheck()still saves the approval-gated calls as pending (status: 'awaiting_approval'), but it does not execute the auto-approved calls.What changed
packages/agent/src/lib/model-result.ts: new optionalskipAutoExecutionparam onhandleApprovalCheck(); first-response call site checksstopWhenfirst.packages/agent/tests/unit/stop-when-before-approval.test.ts: new regression test..changeset/stop-when-before-approval.md: patch changeset.Decisions:
allowFinalResponseisfalse. With the default (allowFinalResponseon), a stop triggered bystopWhenalready runs the pending calls of the last response (throughhandleApprovalCheck()) before the finaltoolChoice: 'none'request. So with the default, running the auto sibling when the stop condition is met is existing behavior (the final-response path executes them so they have matching outputs), not a bypass. Gating it there would change the behavior only on the first response and make it inconsistent with later rounds.unsentToolResults(not dropped). On resume, every function call in the paused response still gets a matching output, so the follow-up request stays valid.Testing
stopWhen is evaluated before the approval check on the first response > does not run an auto-executable sibling of an approval-gated call when stopWhen is already met: always-truestopWhen+allowFinalResponse: false+ one auto-executable tool + onerequireApprovalsibling in the same response. Asserts the auto tool runs 0 times and the approval call is saved pending. Fails onmain(expected "vi.fn()" to not be called at all, but actually been called 1 times), passes with this change.packages/agent:biome check src tests,pnpm run typecheck,pnpm run buildandvitest --run --project unit(108 files, 1246 tests) all pass. Transport is mocked; no network calls.Existing-PR search: searched open and closed PRs from the last 90 days (
stopWhen approval,shouldStopExecution,stop condition auto-approve,SEC-768) and read #131 and #133. Neither changes this ordering; both touch approval/batch validation in the same file, so a small textual rebase may be needed but there is no logic overlap.Security hardening fix. Fixes SEC-768
Link to Devin session: https://openrouter.devinenterprise.com/sessions/c212b5ff3bbc45e2b63007752496eb03
Open in Devin Desktop: https://openrouter.devinenterprise.com/desktop/session/c212b5ff3bbc45e2b63007752496eb03?variant=devin
Requested by: @alexb-openrouter