Repository: All-Hands-AI/OpenHands
File: openhands-cli/openhands_cli/user_actions/agent_action.py (Python)

Code before:
        print_formatted_text(
            HTML(f'<grey>  {i}. {tool_name}: {html.escape(action_content)}...</grey>')
        )

    question = 'Choose an option:'
    options = [
        'Yes, proceed',
        'Reject',
        "Always proceed (don't ask again)",
    ]

    if not using_risk_based_policy:
        options.append('Auto-confirm LOW/MEDIUM risk, ask for HIGH risk')

    try:
        index = cli_confirm(question, options, escapable=True)
    except (EOFError, KeyboardInterrupt):
        print_formatted_text(HTML('\n<red>No input received; pausing agent.</red>'))
        return ConfirmationResult(decision=UserConfirmation.DEFER)

    if index == 0:
        return ConfirmationResult(decision=UserConfirmation.ACCEPT)
    elif index == 1:
        # Handle "Reject" option with optional reason
        try:
            reason = cli_text_input('Reason (ENTER to reject without reason): ').strip()
        except (EOFError, KeyboardInterrupt):
            return ConfirmationResult(decision=UserConfirmation.DEFER)

        return ConfirmationResult(decision=UserConfirmation.REJECT, reason=reason)
    elif index == 2:
        return ConfirmationResult(
            decision=UserConfirmation.ACCEPT, policy_change=NeverConfirm()
        )
    elif index == 3:
        return ConfirmationResult(
            decision=UserConfirmation.ACCEPT,
            policy_change=ConfirmRisky(threshold=SecurityRisk.HIGH),
        )

    return ConfirmationResult(decision=UserConfirmation.REJECT)


Review comment (suggestion):
```suggestion
            reason = cli_text_input('Reason (and let OpenHands know why): ').strip()
```
It's always possible to enter an empty user message, if people want to, right? I don't know if we need to document that. I'd guess most of the time one doesn't want the LLM to do the thing, so they'd say something.

IIRC this is also Claude behavior, so I feel it's probably what users expect.

Code after:
        print_formatted_text(
            HTML(f'<grey>  {i}. {tool_name}: {html.escape(action_content)}...</grey>')
        )

    question = 'Choose an option:'
    options = [
        'Yes, proceed',
        'Reject',
        "Always proceed (don't ask again)",
    ]

    if not using_risk_based_policy:
        options.append('Auto-confirm LOW/MEDIUM risk, ask for HIGH risk')

    try:
        index = cli_confirm(question, options, escapable=True)
    except (EOFError, KeyboardInterrupt):
        print_formatted_text(HTML('\n<red>No input received; pausing agent.</red>'))
        return ConfirmationResult(decision=UserConfirmation.DEFER)

    if index == 0:
        return ConfirmationResult(decision=UserConfirmation.ACCEPT)
    elif index == 1:
        # Handle "Reject" option with optional reason
        try:
            reason = cli_text_input('Reason (and let OpenHands know why): ').strip()
        except (EOFError, KeyboardInterrupt):
            return ConfirmationResult(decision=UserConfirmation.DEFER)

        return ConfirmationResult(decision=UserConfirmation.REJECT, reason=reason)
    elif index == 2:
        return ConfirmationResult(
            decision=UserConfirmation.ACCEPT, policy_change=NeverConfirm()
        )
    elif index == 3:
        return ConfirmationResult(
            decision=UserConfirmation.ACCEPT,
            policy_change=ConfirmRisky(threshold=SecurityRisk.HIGH),
        )

    return ConfirmationResult(decision=UserConfirmation.REJECT)