Wenchao An 3d826c6d95
feat(approvals): add Ask, Auto and Full tool permission modes (#8033)
* feat(hitl): add human-in-the-loop approval for high-risk tool calls

* fix(hitl): address approval review findings

* docs(hitl): keep agent guidance under size limit

* fix(hitl): guard approval pause recovery

* docs(hitl): shrink inherited guidance

* fix(hitl): harden approval admission and recovery

* fix(approvals): address review safety and reconciliation gaps

* ci: retry approval checks after runner timeout

---------

Co-authored-by: wangzeren <1004695029@qq.com>
2026-11-11 20:59:05 +08:00

31 lines
1.2 KiB
Python

"""Shared approval batching and resume normalization, including legacy pauses."""
from collections.abc import Mapping
def approval_responses(resume):
if not isinstance(resume, Mapping):
return None
responses = resume.get("responses")
if isinstance(responses, list):
return responses
groups = list(resume.values())
if groups and all(isinstance(value, Mapping) and isinstance(value.get("responses"), list) for value in groups):
return [response for value in groups for response in value["responses"]]
return None
def combine_approval_payloads(payloads):
if not payloads:
return None
first = payloads[0]
if len(payloads) == 1:
return first
allowed = first.get("allowed_decisions", ["approve", "reject"])
return {
**first,
"actions": [action for payload in payloads for action in payload.get("actions", [])],
"pending_tool_call_ids": [call_id for payload in payloads for call_id in payload.get("pending_tool_call_ids", [])],
"allowed_decisions": [decision for decision in allowed if all(decision in payload.get("allowed_decisions", []) for payload in payloads)],
}