fix(soul): carry approval cancellation feedback to ApprovalResult - #1979
Merged
wbxl2000 merged 2 commits intoApr 22, 2026
Conversation
When the 300s safety timeout in wait_for_response fires (e.g. the user steps away from their SSH session), _cancel_request sets request.feedback="approval timed out" on the record before raising ApprovalCancelledError. The outer Approval.request was dropping that feedback when constructing the ApprovalResult, so the downstream ToolRejectedError fell back to the generic "Rejected by user" brief -- leaving users returning to their terminal unable to distinguish a timeout from a manual rejection. Read record.feedback back through the existing get_request API and pass it into ApprovalResult. The rejection surface now reads "Rejected: approval timed out" on the timeout path, and stays backward-compatible for any cancel path that doesn't set feedback. Adds: - Assertion on the existing runtime timeout test that record.feedback is persisted as "approval timed out" - New regression test driving Approval.request through the cancellation path and asserting both ApprovalResult.feedback and rejection_error().brief surface the reason Related to MoonshotAI#1823 (only addresses the UX/display aspect; the broader configurable-timeout feature request is tracked by MoonshotAI#1837).
wbxl2000
force-pushed
the
fix/approval-timeout-feedback
branch
from
April 21, 2026 14:07
6a5f126 to
214a609
Compare
Signed-off-by: Kai <me@kaiyi.cool>
RealKai42
approved these changes
Apr 22, 2026
Collaborator
Author
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.


Related Issue
Related to #1823 — addresses only the UX/display aspect described in the issue (the
Rejected by usermisleading message on timeout). Does not resolve #1823; the broader configurable timeout feature request is already being tracked by #1837.Description
Bug
When the 300 s safety timeout in
ApprovalRuntime.wait_for_responsefires (e.g. the user stepped away from their SSH/tmux session),_cancel_requestwritesrequest.feedback = "approval timed out"to the record before raisingApprovalCancelledError:But the outer
Approval.requestwas dropping that feedback:With empty
feedback,ApprovalResult.rejection_error()fell back toToolRejectedError()'s defaultRejected by userbrief — so users returning to their terminal saw a message implying they had manually rejected the tool call, when they had just walked away.Fix
Read the feedback back from the record via the existing public
get_requestAPI:After the fix, the rejection surface reads:
Rejected: approval timed outThe tool call is rejected by the user. User feedback: approval timed outThe
if record else ""fallback preserves pre-fix behavior for the theoreticalrecord is Nonecase, and the read-from-record approach keeps all cancel paths uniform without inflatingApprovalCancelledErrorwith state.Tests
test_approval_runtime_wait_for_response_times_outto assertrecord.feedback == "approval timed out"after timeout (guards the upstream invariant the fix depends on).test_approval_request_timeout_carries_feedback_to_resultexercisingApproval.requestthrough the cancellation path; asserts bothApprovalResult.feedbackround-trips andrejection_error().brief == "Rejected: approval timed out". Verified locally that reverting the fix makes this test fail withAssertionError: assert '' == 'approval timed out'.Checklist
CHANGELOG.md+ en/zh release-notes mirrors).