mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
[codex-rs] Add writes app approval mode (#30482)
## Summary - Adds `writes` to `AppToolApproval` and exposes it through config and app-server schemas, including `[apps._default].default_tools_approval_mode`. - In `writes`, tools with `readOnlyHint = true` skip approval; all other tools prompt, including non-destructive writes and tools without annotations. - Prevents session or persistent approval choices in this mode so later writes still prompt. ## Why `auto` only prompts for risk-hinted actions, while `prompt` also interrupts reads. Apps need a middle mode that gates writes without prompting for declared read-only actions. ## Validation - `just write-config-schema` - `just write-app-server-schema` - `just fmt` - `just test -p codex-core mcp_turn_metadata` (4 passed) - `just test -p codex-core writes_mode` (2 passed) - `just test -p codex-app-server config_read_includes_apps` (1 passed) - `just test -p codex-app-server-protocol` (251 passed) - `just test -p codex-config` (200 passed) - `just test -p codex-cli` (300 passed) - `just fix -p codex-core -p codex-config -p codex-app-server-protocol -p codex-app-server -p codex-cli`
This commit is contained in:
1 parent
8841f506c0
commit
f6e251c3ac
15 files changed
+198
-23
No files matched your search
@@ -1223,8 +1223,7 @@ async fn maybe_request_mcp_tool_approval(
|
||||
}
|
||||
|
||||
let annotations = metadata.and_then(|metadata| metadata.annotations.as_ref());
|
||||
let approval_required = requires_mcp_tool_approval(annotations);
|
||||
if !approval_required && approval_mode != AppToolApproval::Prompt {
|
||||
if !requires_mcp_tool_approval_for_mode(annotations, approval_mode) {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -1927,12 +1926,13 @@ fn normalize_approval_decision_for_mode(
|
||||
decision: McpToolApprovalDecision,
|
||||
approval_mode: AppToolApproval,
|
||||
) -> McpToolApprovalDecision {
|
||||
if approval_mode == AppToolApproval::Prompt
|
||||
&& matches!(
|
||||
decision,
|
||||
McpToolApprovalDecision::AcceptForSession | McpToolApprovalDecision::AcceptAndRemember
|
||||
)
|
||||
{
|
||||
if matches!(
|
||||
approval_mode,
|
||||
AppToolApproval::Prompt | AppToolApproval::Writes
|
||||
) && matches!(
|
||||
decision,
|
||||
McpToolApprovalDecision::AcceptForSession | McpToolApprovalDecision::AcceptAndRemember
|
||||
) {
|
||||
McpToolApprovalDecision::Accept
|
||||
} else {
|
||||
decision
|
||||
@@ -2179,6 +2179,20 @@ fn requires_mcp_tool_approval(annotations: Option<&ToolAnnotations>) -> bool {
|
||||
.unwrap_or(true)
|
||||
}
|
||||
|
||||
fn requires_mcp_tool_approval_for_mode(
|
||||
annotations: Option<&ToolAnnotations>,
|
||||
approval_mode: AppToolApproval,
|
||||
) -> bool {
|
||||
match approval_mode {
|
||||
AppToolApproval::Auto => requires_mcp_tool_approval(annotations),
|
||||
AppToolApproval::Prompt => true,
|
||||
AppToolApproval::Writes => !annotations
|
||||
.and_then(|annotations| annotations.read_only_hint)
|
||||
.unwrap_or(false),
|
||||
AppToolApproval::Approve => false,
|
||||
}
|
||||
}
|
||||
|
||||
async fn notify_mcp_tool_call_skip(
|
||||
sess: &Session,
|
||||
turn_context: &TurnContext,
|
||||
|
||||
Reference in new issue
Block a user