feat(03-02): implement ApprovalHandler class
- Add ApprovalState dataclass for approval workflow state - Add ApprovalHandler class with: - APPROVAL_PATTERNS for detection (AskUserQuestion, ExitPlanMode, 需要确认, Please confirm) - detect_approval_request() to find approval requests in output - create_approval_card() with confirm/reject buttons using CardButton - handle_callback() to process approval actions - In-memory pending_approvals cache - Fix test assertions to use kwargs instead of positional args All 8 tests pass for approval handling. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -60,8 +60,8 @@ class TestApprovalHandlerCardCreation:
|
||||
card = handler.create_approval_card(context, "session-123", "test-project")
|
||||
|
||||
formatter.format_info.assert_called_once()
|
||||
call_args = formatter.format_info.call_args
|
||||
assert call_args[0][0] == "需要确认"
|
||||
call_kwargs = formatter.format_info.call_args.kwargs
|
||||
assert call_kwargs.get("title") == "需要确认"
|
||||
|
||||
def test_create_approval_card_has_confirm_button(self):
|
||||
"""create_approval_card has confirm button with action='approve'."""
|
||||
@@ -79,8 +79,8 @@ class TestApprovalHandlerCardCreation:
|
||||
card = handler.create_approval_card(context, "session-123", "test-project")
|
||||
|
||||
# Check that format_info was called with buttons
|
||||
call_args = formatter.format_info.call_args
|
||||
buttons = call_args[1].get('buttons') or (call_args[0][2] if len(call_args[0]) > 2 else None)
|
||||
call_kwargs = formatter.format_info.call_args.kwargs
|
||||
buttons = call_kwargs.get('buttons')
|
||||
assert buttons is not None
|
||||
# Find confirm button
|
||||
confirm_btn = next((b for b in buttons if b.value.get("action") == "approve"), None)
|
||||
@@ -103,8 +103,8 @@ class TestApprovalHandlerCardCreation:
|
||||
card = handler.create_approval_card(context, "session-123", "test-project")
|
||||
|
||||
# Check that format_info was called with buttons
|
||||
call_args = formatter.format_info.call_args
|
||||
buttons = call_args[1].get('buttons') or (call_args[0][2] if len(call_args[0]) > 2 else None)
|
||||
call_kwargs = formatter.format_info.call_args.kwargs
|
||||
buttons = call_kwargs.get('buttons')
|
||||
assert buttons is not None
|
||||
# Find reject button
|
||||
reject_btn = next((b for b in buttons if b.value.get("action") == "reject"), None)
|
||||
|
||||
Reference in New Issue
Block a user