mirror of
https://github.com/openai/codex.git
synced 2026-10-30 19:18:49 +00:00
feat: introduce Reject variant of AskForApproval
This commit is contained in:
@@ -69,13 +69,46 @@
|
||||
"type": "object"
|
||||
},
|
||||
"AskForApproval": {
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"AskForApproval2": {
|
||||
"description": "Determines the conditions under which the user is consulted to approve running the command proposed by Codex.",
|
||||
@@ -101,6 +134,39 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"description": "Fine-grained rejection controls for approval prompts.\n\nWhen a field is `true`, prompts of that category are automatically rejected instead of shown to the user.",
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"description": "Reject MCP elicitation prompts.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"description": "Reject prompts triggered by execpolicy `prompt` rules.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"description": "Reject approval prompts related to sandbox escalation.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval2",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Never ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.",
|
||||
"enum": [
|
||||
|
||||
@@ -117,6 +117,39 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"description": "Fine-grained rejection controls for approval prompts.\n\nWhen a field is `true`, prompts of that category are automatically rejected instead of shown to the user.",
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"description": "Reject MCP elicitation prompts.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"description": "Reject prompts triggered by execpolicy `prompt` rules.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"description": "Reject approval prompts related to sandbox escalation.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Never ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.",
|
||||
"enum": [
|
||||
|
||||
@@ -454,6 +454,39 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"description": "Fine-grained rejection controls for approval prompts.\n\nWhen a field is `true`, prompts of that category are automatically rejected instead of shown to the user.",
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"description": "Reject MCP elicitation prompts.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"description": "Reject prompts triggered by execpolicy `prompt` rules.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"description": "Reject approval prompts related to sandbox escalation.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Never ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.",
|
||||
"enum": [
|
||||
|
||||
@@ -221,6 +221,39 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"description": "Fine-grained rejection controls for approval prompts.\n\nWhen a field is `true`, prompts of that category are automatically rejected instead of shown to the user.",
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"description": "Reject MCP elicitation prompts.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"description": "Reject prompts triggered by execpolicy `prompt` rules.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"description": "Reject approval prompts related to sandbox escalation.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Never ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.",
|
||||
"enum": [
|
||||
@@ -10667,13 +10700,46 @@
|
||||
"type": "object"
|
||||
},
|
||||
"AskForApproval": {
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"AuthMode": {
|
||||
"description": "Authentication mode for OpenAI-backed providers.",
|
||||
|
||||
@@ -25,6 +25,39 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"description": "Fine-grained rejection controls for approval prompts.\n\nWhen a field is `true`, prompts of that category are automatically rejected instead of shown to the user.",
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"description": "Reject MCP elicitation prompts.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"description": "Reject prompts triggered by execpolicy `prompt` rules.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"description": "Reject approval prompts related to sandbox escalation.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Never ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.",
|
||||
"enum": [
|
||||
|
||||
@@ -117,6 +117,39 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"description": "Fine-grained rejection controls for approval prompts.\n\nWhen a field is `true`, prompts of that category are automatically rejected instead of shown to the user.",
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"description": "Reject MCP elicitation prompts.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"description": "Reject prompts triggered by execpolicy `prompt` rules.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"description": "Reject approval prompts related to sandbox escalation.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Never ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.",
|
||||
"enum": [
|
||||
|
||||
@@ -29,6 +29,39 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"description": "Fine-grained rejection controls for approval prompts.\n\nWhen a field is `true`, prompts of that category are automatically rejected instead of shown to the user.",
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"description": "Reject MCP elicitation prompts.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"description": "Reject prompts triggered by execpolicy `prompt` rules.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"description": "Reject approval prompts related to sandbox escalation.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Never ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.",
|
||||
"enum": [
|
||||
|
||||
@@ -25,6 +25,39 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"description": "Fine-grained rejection controls for approval prompts.\n\nWhen a field is `true`, prompts of that category are automatically rejected instead of shown to the user.",
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"description": "Reject MCP elicitation prompts.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"description": "Reject prompts triggered by execpolicy `prompt` rules.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"description": "Reject approval prompts related to sandbox escalation.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Never ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.",
|
||||
"enum": [
|
||||
|
||||
@@ -25,6 +25,39 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"description": "Fine-grained rejection controls for approval prompts.\n\nWhen a field is `true`, prompts of that category are automatically rejected instead of shown to the user.",
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"description": "Reject MCP elicitation prompts.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"description": "Reject prompts triggered by execpolicy `prompt` rules.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"description": "Reject approval prompts related to sandbox escalation.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Never ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.",
|
||||
"enum": [
|
||||
|
||||
@@ -117,6 +117,39 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"description": "Fine-grained rejection controls for approval prompts.\n\nWhen a field is `true`, prompts of that category are automatically rejected instead of shown to the user.",
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"description": "Reject MCP elicitation prompts.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"description": "Reject prompts triggered by execpolicy `prompt` rules.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"description": "Reject approval prompts related to sandbox escalation.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Never ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.",
|
||||
"enum": [
|
||||
|
||||
@@ -29,6 +29,39 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"description": "Fine-grained rejection controls for approval prompts.\n\nWhen a field is `true`, prompts of that category are automatically rejected instead of shown to the user.",
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"description": "Reject MCP elicitation prompts.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"description": "Reject prompts triggered by execpolicy `prompt` rules.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"description": "Reject approval prompts related to sandbox escalation.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Never ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.",
|
||||
"enum": [
|
||||
|
||||
@@ -117,6 +117,39 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"description": "Fine-grained rejection controls for approval prompts.\n\nWhen a field is `true`, prompts of that category are automatically rejected instead of shown to the user.",
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"description": "Reject MCP elicitation prompts.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"description": "Reject prompts triggered by execpolicy `prompt` rules.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"description": "Reject approval prompts related to sandbox escalation.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Never ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.",
|
||||
"enum": [
|
||||
|
||||
@@ -47,13 +47,46 @@
|
||||
"type": "object"
|
||||
},
|
||||
"AskForApproval": {
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Config": {
|
||||
"additionalProperties": true,
|
||||
|
||||
@@ -2,13 +2,46 @@
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AskForApproval": {
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ConfigRequirements": {
|
||||
"properties": {
|
||||
|
||||
@@ -2,13 +2,46 @@
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AskForApproval": {
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"SandboxMode": {
|
||||
"enum": [
|
||||
|
||||
@@ -6,13 +6,46 @@
|
||||
"type": "string"
|
||||
},
|
||||
"AskForApproval": {
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ByteRange": {
|
||||
"properties": {
|
||||
|
||||
@@ -2,13 +2,46 @@
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AskForApproval": {
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ContentItem": {
|
||||
"oneOf": [
|
||||
|
||||
@@ -6,13 +6,46 @@
|
||||
"type": "string"
|
||||
},
|
||||
"AskForApproval": {
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ByteRange": {
|
||||
"properties": {
|
||||
|
||||
@@ -2,13 +2,46 @@
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AskForApproval": {
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"DynamicToolSpec": {
|
||||
"properties": {
|
||||
|
||||
@@ -6,13 +6,46 @@
|
||||
"type": "string"
|
||||
},
|
||||
"AskForApproval": {
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ByteRange": {
|
||||
"properties": {
|
||||
|
||||
@@ -6,13 +6,46 @@
|
||||
"type": "string"
|
||||
},
|
||||
"AskForApproval": {
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"title": "RejectAskForApproval",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ByteRange": {
|
||||
"properties": {
|
||||
|
||||
@@ -6,4 +6,16 @@
|
||||
* Determines the conditions under which the user is consulted to approve
|
||||
* running the command proposed by Codex.
|
||||
*/
|
||||
export type AskForApproval = "untrusted" | "on-failure" | "on-request" | "never";
|
||||
export type AskForApproval = "untrusted" | "on-failure" | "on-request" | { "reject": {
|
||||
/**
|
||||
* Reject approval prompts related to sandbox escalation.
|
||||
*/
|
||||
sandbox_approval: boolean,
|
||||
/**
|
||||
* Reject prompts triggered by execpolicy `prompt` rules.
|
||||
*/
|
||||
rules: boolean,
|
||||
/**
|
||||
* Reject MCP elicitation prompts.
|
||||
*/
|
||||
mcp_elicitations: boolean, } } | "never";
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type AskForApproval = "untrusted" | "on-failure" | "on-request" | "never";
|
||||
export type AskForApproval = "untrusted" | "on-failure" | "on-request" | { "reject": { sandbox_approval: boolean, rules: boolean, mcp_elicitations: boolean, } } | "never";
|
||||
|
||||
@@ -161,6 +161,11 @@ pub enum AskForApproval {
|
||||
UnlessTrusted,
|
||||
OnFailure,
|
||||
OnRequest,
|
||||
Reject {
|
||||
sandbox_approval: bool,
|
||||
rules: bool,
|
||||
mcp_elicitations: bool,
|
||||
},
|
||||
Never,
|
||||
}
|
||||
|
||||
@@ -170,6 +175,15 @@ impl AskForApproval {
|
||||
AskForApproval::UnlessTrusted => CoreAskForApproval::UnlessTrusted,
|
||||
AskForApproval::OnFailure => CoreAskForApproval::OnFailure,
|
||||
AskForApproval::OnRequest => CoreAskForApproval::OnRequest,
|
||||
AskForApproval::Reject {
|
||||
sandbox_approval,
|
||||
rules,
|
||||
mcp_elicitations,
|
||||
} => CoreAskForApproval::Reject {
|
||||
sandbox_approval,
|
||||
rules,
|
||||
mcp_elicitations,
|
||||
},
|
||||
AskForApproval::Never => CoreAskForApproval::Never,
|
||||
}
|
||||
}
|
||||
@@ -181,6 +195,15 @@ impl From<CoreAskForApproval> for AskForApproval {
|
||||
CoreAskForApproval::UnlessTrusted => AskForApproval::UnlessTrusted,
|
||||
CoreAskForApproval::OnFailure => AskForApproval::OnFailure,
|
||||
CoreAskForApproval::OnRequest => AskForApproval::OnRequest,
|
||||
CoreAskForApproval::Reject {
|
||||
sandbox_approval,
|
||||
rules,
|
||||
mcp_elicitations,
|
||||
} => AskForApproval::Reject {
|
||||
sandbox_approval,
|
||||
rules,
|
||||
mcp_elicitations,
|
||||
},
|
||||
CoreAskForApproval::Never => AskForApproval::Never,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,6 +133,77 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"description": "Fine-grained rejection controls for approval prompts.\n\nWhen a field is `true`, prompts of that category are automatically rejected instead of shown to the user.",
|
||||
"properties": {
|
||||
"reject": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"description": "Reject MCP elicitation prompts.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"description": "Reject prompts triggered by execpolicy `prompt` rules.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"description": "Reject approval prompts related to sandbox escalation.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reject"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Never ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.",
|
||||
"enum": [
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"AskForApprovalToml": {
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Under this policy, only \"known safe\" commands—those matching `is_safe_command()` and performing read-only file operations—are auto-approved. Everything else will ask the user to approve.",
|
||||
"enum": [
|
||||
"untrusted"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "DEPRECATED: *All* commands are auto-approved, but they are expected to run inside a sandbox where network access is disabled and writes are confined to a specific set of paths. If the command fails, it will be escalated to the user to approve execution without a sandbox. Prefer `OnRequest` for interactive runs or `Never` for non-interactive runs.",
|
||||
"enum": [
|
||||
"on-failure"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "The model decides when to ask the user for approval.",
|
||||
"enum": [
|
||||
"on-request"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "Reject sandbox escalation approvals by default, while still allowing rule-driven prompts and MCP elicitations.",
|
||||
"enum": [
|
||||
"reject"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "Never ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.",
|
||||
"enum": [
|
||||
@@ -1280,7 +1351,7 @@
|
||||
"approval_policy": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AskForApproval"
|
||||
"$ref": "#/definitions/AskForApprovalToml"
|
||||
}
|
||||
],
|
||||
"description": "Default approval policy for executing commands."
|
||||
|
||||
@@ -1380,10 +1380,9 @@ impl Session {
|
||||
required_mcp_servers.sort();
|
||||
let cancel_token = sess.mcp_startup_cancellation_token().await;
|
||||
|
||||
sess.services
|
||||
.mcp_connection_manager
|
||||
.write()
|
||||
.await
|
||||
let mut mcp_connection_manager = sess.services.mcp_connection_manager.write().await;
|
||||
mcp_connection_manager.set_approval_policy(&session_configuration.approval_policy);
|
||||
mcp_connection_manager
|
||||
.initialize(
|
||||
&mcp_servers,
|
||||
config.mcp_oauth_credentials_store_mode,
|
||||
@@ -1393,6 +1392,7 @@ impl Session {
|
||||
sandbox_state,
|
||||
)
|
||||
.await;
|
||||
drop(mcp_connection_manager);
|
||||
if !required_mcp_servers.is_empty() {
|
||||
let failures = sess
|
||||
.services
|
||||
@@ -1828,6 +1828,11 @@ impl Session {
|
||||
sandbox_policy_changed: bool,
|
||||
) -> Arc<TurnContext> {
|
||||
let per_turn_config = Self::build_per_turn_config(&session_configuration);
|
||||
self.services
|
||||
.mcp_connection_manager
|
||||
.read()
|
||||
.await
|
||||
.set_approval_policy(&session_configuration.approval_policy);
|
||||
|
||||
if sandbox_policy_changed {
|
||||
let sandbox_state = SandboxState {
|
||||
|
||||
@@ -893,7 +893,7 @@ pub struct ConfigToml {
|
||||
pub model_auto_compact_token_limit: Option<i64>,
|
||||
|
||||
/// Default approval policy for executing commands.
|
||||
pub approval_policy: Option<AskForApproval>,
|
||||
pub approval_policy: Option<AskForApprovalToml>,
|
||||
|
||||
#[serde(default)]
|
||||
pub shell_environment_policy: ShellEnvironmentPolicyToml,
|
||||
@@ -1113,7 +1113,7 @@ impl From<ConfigToml> for UserSavedConfig {
|
||||
.collect();
|
||||
|
||||
Self {
|
||||
approval_policy: config_toml.approval_policy,
|
||||
approval_policy: config_toml.approval_policy.map(Into::into),
|
||||
sandbox_mode: config_toml.sandbox_mode,
|
||||
sandbox_settings: config_toml.sandbox_workspace_write.map(From::from),
|
||||
forced_chatgpt_workspace_id: config_toml.forced_chatgpt_workspace_id,
|
||||
@@ -1129,6 +1129,48 @@ impl From<ConfigToml> for UserSavedConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// Version of [AskForApproval] that is deserializable from config.toml.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum AskForApprovalToml {
|
||||
#[serde(rename = "untrusted")]
|
||||
UnlessTrusted,
|
||||
OnFailure,
|
||||
OnRequest,
|
||||
Reject,
|
||||
Never,
|
||||
}
|
||||
|
||||
impl AskForApprovalToml {
|
||||
pub fn to_core(self) -> AskForApproval {
|
||||
match self {
|
||||
AskForApprovalToml::UnlessTrusted => AskForApproval::UnlessTrusted,
|
||||
AskForApprovalToml::OnFailure => AskForApproval::OnFailure,
|
||||
AskForApprovalToml::OnRequest => AskForApproval::OnRequest,
|
||||
AskForApprovalToml::Reject => AskForApproval::reject_defaults(),
|
||||
AskForApprovalToml::Never => AskForApproval::Never,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AskForApproval> for AskForApprovalToml {
|
||||
fn from(value: AskForApproval) -> Self {
|
||||
match value {
|
||||
AskForApproval::UnlessTrusted => AskForApprovalToml::UnlessTrusted,
|
||||
AskForApproval::OnFailure => AskForApprovalToml::OnFailure,
|
||||
AskForApproval::OnRequest => AskForApprovalToml::OnRequest,
|
||||
AskForApproval::Reject { .. } => AskForApprovalToml::Reject,
|
||||
AskForApproval::Never => AskForApprovalToml::Never,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AskForApprovalToml> for AskForApproval {
|
||||
fn from(value: AskForApprovalToml) -> Self {
|
||||
value.to_core()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct ProjectConfig {
|
||||
@@ -1571,7 +1613,7 @@ impl Config {
|
||||
|| cfg.approval_policy.is_some();
|
||||
let mut approval_policy = approval_policy_override
|
||||
.or(config_profile.approval_policy)
|
||||
.or(cfg.approval_policy)
|
||||
.or(cfg.approval_policy.map(Into::into))
|
||||
.unwrap_or_else(|| {
|
||||
if active_project.is_trusted() {
|
||||
AskForApproval::OnRequest
|
||||
|
||||
@@ -32,6 +32,10 @@ use shlex::try_join as shlex_try_join;
|
||||
|
||||
const PROMPT_CONFLICT_REASON: &str =
|
||||
"approval required by policy, but AskForApproval is set to Never";
|
||||
const REJECT_SANDBOX_APPROVAL_REASON: &str =
|
||||
"approval required by policy, but AskForApproval::Reject.sandbox_approval is set";
|
||||
const REJECT_RULES_APPROVAL_REASON: &str =
|
||||
"approval required by policy rule, but AskForApproval::Reject.rules is set";
|
||||
const RULES_DIR_NAME: &str = "rules";
|
||||
const RULE_EXTENSION: &str = "rules";
|
||||
const DEFAULT_POLICY_FILE: &str = "default.rules";
|
||||
@@ -91,6 +95,30 @@ fn is_policy_match(rule_match: &RuleMatch) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
fn prompt_is_from_policy_rule(evaluation: &Evaluation) -> bool {
|
||||
evaluation
|
||||
.matched_rules
|
||||
.iter()
|
||||
.any(|rule_match| is_policy_match(rule_match) && rule_match.decision() == Decision::Prompt)
|
||||
}
|
||||
|
||||
fn prompt_is_rejected_by_policy(
|
||||
approval_policy: AskForApproval,
|
||||
prompt_is_rule: bool,
|
||||
) -> Option<&'static str> {
|
||||
match approval_policy {
|
||||
AskForApproval::Never => Some(PROMPT_CONFLICT_REASON),
|
||||
AskForApproval::Reject { rules: true, .. } if prompt_is_rule => {
|
||||
Some(REJECT_RULES_APPROVAL_REASON)
|
||||
}
|
||||
AskForApproval::Reject {
|
||||
sandbox_approval: true,
|
||||
..
|
||||
} if !prompt_is_rule => Some(REJECT_SANDBOX_APPROVAL_REASON),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ExecPolicyError {
|
||||
#[error("failed to read rules files from {dir}: {source}")]
|
||||
@@ -196,9 +224,11 @@ impl ExecPolicyManager {
|
||||
reason: derive_forbidden_reason(command, &evaluation),
|
||||
},
|
||||
Decision::Prompt => {
|
||||
if matches!(approval_policy, AskForApproval::Never) {
|
||||
let prompt_is_rule = prompt_is_from_policy_rule(&evaluation);
|
||||
if let Some(reason) = prompt_is_rejected_by_policy(approval_policy, prompt_is_rule)
|
||||
{
|
||||
ExecApprovalRequirement::Forbidden {
|
||||
reason: PROMPT_CONFLICT_REASON.to_string(),
|
||||
reason: reason.to_string(),
|
||||
}
|
||||
} else {
|
||||
ExecApprovalRequirement::NeedsApproval {
|
||||
@@ -465,6 +495,20 @@ pub fn render_decision_for_unmatched_command(
|
||||
}
|
||||
}
|
||||
}
|
||||
AskForApproval::Reject { .. } => match sandbox_policy {
|
||||
SandboxPolicy::DangerFullAccess | SandboxPolicy::ExternalSandbox { .. } => {
|
||||
// Mirror on-request behavior for unmatched commands; prompt-vs-reject is handled
|
||||
// by `prompt_is_rejected_by_policy`.
|
||||
Decision::Allow
|
||||
}
|
||||
SandboxPolicy::ReadOnly { .. } | SandboxPolicy::WorkspaceWrite { .. } => {
|
||||
if sandbox_permissions.requires_escalated_permissions() {
|
||||
Decision::Prompt
|
||||
} else {
|
||||
Decision::Allow
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ use codex_async_utils::OrCancelExt;
|
||||
use codex_protocol::approvals::ElicitationRequestEvent;
|
||||
use codex_protocol::mcp::CallToolResult;
|
||||
use codex_protocol::mcp::RequestId as ProtocolRequestId;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
use codex_protocol::protocol::Event;
|
||||
use codex_protocol::protocol::EventMsg;
|
||||
use codex_protocol::protocol::McpStartupCompleteEvent;
|
||||
@@ -44,6 +45,7 @@ use futures::future::FutureExt;
|
||||
use futures::future::Shared;
|
||||
use rmcp::model::ClientCapabilities;
|
||||
use rmcp::model::CreateElicitationRequestParams;
|
||||
use rmcp::model::ElicitationAction;
|
||||
use rmcp::model::ElicitationCapability;
|
||||
use rmcp::model::FormElicitationCapability;
|
||||
use rmcp::model::Implementation;
|
||||
@@ -71,6 +73,7 @@ use tracing::instrument;
|
||||
use tracing::warn;
|
||||
|
||||
use crate::codex::INITIAL_SUBMIT_ID;
|
||||
use crate::config::Constrained;
|
||||
use crate::config::types::McpServerConfig;
|
||||
use crate::config::types::McpServerTransportConfig;
|
||||
|
||||
@@ -182,9 +185,19 @@ static CODEX_APPS_TOOLS_CACHE: LazyLock<StdMutex<Option<CachedCodexAppsTools>>>
|
||||
|
||||
type ResponderMap = HashMap<(String, RequestId), oneshot::Sender<ElicitationResponse>>;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
#[derive(Clone)]
|
||||
struct ElicitationRequestManager {
|
||||
requests: Arc<Mutex<ResponderMap>>,
|
||||
approval_policy: Arc<StdMutex<AskForApproval>>,
|
||||
}
|
||||
|
||||
impl Default for ElicitationRequestManager {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
requests: Arc::new(Mutex::new(HashMap::new())),
|
||||
approval_policy: Arc::new(StdMutex::new(AskForApproval::default())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ElicitationRequestManager {
|
||||
@@ -205,11 +218,23 @@ impl ElicitationRequestManager {
|
||||
|
||||
fn make_sender(&self, server_name: String, tx_event: Sender<Event>) -> SendElicitation {
|
||||
let elicitation_requests = self.requests.clone();
|
||||
let approval_policy = self.approval_policy.clone();
|
||||
Box::new(move |id, elicitation| {
|
||||
let elicitation_requests = elicitation_requests.clone();
|
||||
let tx_event = tx_event.clone();
|
||||
let server_name = server_name.clone();
|
||||
let approval_policy = approval_policy.clone();
|
||||
async move {
|
||||
if approval_policy
|
||||
.lock()
|
||||
.is_ok_and(|policy| policy.rejects_mcp_elicitations())
|
||||
{
|
||||
return Ok(ElicitationResponse {
|
||||
action: ElicitationAction::Decline,
|
||||
content: None,
|
||||
});
|
||||
}
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
{
|
||||
let mut lock = elicitation_requests.lock().await;
|
||||
@@ -357,6 +382,12 @@ impl McpConnectionManager {
|
||||
!self.clients.is_empty()
|
||||
}
|
||||
|
||||
pub(crate) fn set_approval_policy(&self, approval_policy: &Constrained<AskForApproval>) {
|
||||
if let Ok(mut policy) = self.elicitation_requests.approval_policy.lock() {
|
||||
*policy = approval_policy.value();
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn initialize(
|
||||
&mut self,
|
||||
mcp_servers: &HashMap<String, McpServerConfig>,
|
||||
@@ -371,7 +402,15 @@ impl McpConnectionManager {
|
||||
}
|
||||
let mut clients = HashMap::new();
|
||||
let mut join_set = JoinSet::new();
|
||||
let approval_policy = self
|
||||
.elicitation_requests
|
||||
.approval_policy
|
||||
.lock()
|
||||
.map_or_else(|_| AskForApproval::default(), |policy| *policy);
|
||||
let elicitation_requests = ElicitationRequestManager::default();
|
||||
if let Ok(mut policy) = elicitation_requests.approval_policy.lock() {
|
||||
*policy = approval_policy;
|
||||
}
|
||||
let mcp_servers = mcp_servers.clone();
|
||||
for (server_name, cfg) in mcp_servers.into_iter().filter(|(_, cfg)| cfg.enabled) {
|
||||
let cancel_token = cancel_token.child_token();
|
||||
|
||||
@@ -38,7 +38,10 @@ pub fn assess_patch_safety(
|
||||
}
|
||||
|
||||
match policy {
|
||||
AskForApproval::OnFailure | AskForApproval::Never | AskForApproval::OnRequest => {
|
||||
AskForApproval::OnFailure
|
||||
| AskForApproval::Never
|
||||
| AskForApproval::OnRequest
|
||||
| AskForApproval::Reject { .. } => {
|
||||
// Continue to see if this can be auto-approved.
|
||||
}
|
||||
// TODO(ragona): I'm not sure this is actually correct? I believe in this case
|
||||
@@ -52,7 +55,10 @@ pub fn assess_patch_safety(
|
||||
// possible that paths in the patch are hard links to files outside the
|
||||
// writable roots, so we should still run `apply_patch` in a sandbox in that case.
|
||||
if is_write_patch_constrained_to_writable_paths(action, sandbox_policy, cwd)
|
||||
|| policy == AskForApproval::OnFailure
|
||||
|| matches!(
|
||||
policy,
|
||||
AskForApproval::OnFailure | AskForApproval::Reject { .. }
|
||||
)
|
||||
{
|
||||
if matches!(
|
||||
sandbox_policy,
|
||||
@@ -75,7 +81,14 @@ pub fn assess_patch_safety(
|
||||
None => SafetyCheck::AskUser,
|
||||
}
|
||||
}
|
||||
} else if policy == AskForApproval::Never {
|
||||
} else if matches!(
|
||||
policy,
|
||||
AskForApproval::Never
|
||||
| AskForApproval::Reject {
|
||||
sandbox_approval: true,
|
||||
..
|
||||
}
|
||||
) {
|
||||
SafetyCheck::Reject {
|
||||
reason: "writing outside of the project; rejected by user approval settings"
|
||||
.to_string(),
|
||||
|
||||
@@ -156,6 +156,8 @@ impl ExecApprovalRequirement {
|
||||
|
||||
/// - Never, OnFailure: do not ask
|
||||
/// - OnRequest: ask unless sandbox policy is DangerFullAccess
|
||||
/// - Reject: ask unless sandbox policy is DangerFullAccess, but auto-reject
|
||||
/// when `sandbox_approval` rejection is enabled.
|
||||
/// - UnlessTrusted: always ask
|
||||
pub(crate) fn default_exec_approval_requirement(
|
||||
policy: AskForApproval,
|
||||
@@ -163,14 +165,18 @@ pub(crate) fn default_exec_approval_requirement(
|
||||
) -> ExecApprovalRequirement {
|
||||
let needs_approval = match policy {
|
||||
AskForApproval::Never | AskForApproval::OnFailure => false,
|
||||
AskForApproval::OnRequest => !matches!(
|
||||
AskForApproval::OnRequest | AskForApproval::Reject { .. } => !matches!(
|
||||
sandbox_policy,
|
||||
SandboxPolicy::DangerFullAccess | SandboxPolicy::ExternalSandbox { .. }
|
||||
),
|
||||
AskForApproval::UnlessTrusted => true,
|
||||
};
|
||||
|
||||
if needs_approval {
|
||||
if needs_approval && policy.rejects_sandbox_approval() {
|
||||
ExecApprovalRequirement::Forbidden {
|
||||
reason: "approval policy rejected sandbox approval prompt".to_string(),
|
||||
}
|
||||
} else if needs_approval {
|
||||
ExecApprovalRequirement::NeedsApproval {
|
||||
reason: None,
|
||||
proposed_execpolicy_amendment: None,
|
||||
@@ -224,7 +230,15 @@ pub(crate) trait Approvable<Req> {
|
||||
|
||||
/// Decide we can request an approval for no-sandbox execution.
|
||||
fn wants_no_sandbox_approval(&self, policy: AskForApproval) -> bool {
|
||||
!matches!(policy, AskForApproval::Never | AskForApproval::OnRequest)
|
||||
match policy {
|
||||
AskForApproval::OnFailure => true,
|
||||
AskForApproval::UnlessTrusted => true,
|
||||
AskForApproval::Never => false,
|
||||
AskForApproval::OnRequest => false,
|
||||
AskForApproval::Reject {
|
||||
sandbox_approval, ..
|
||||
} => !sandbox_approval,
|
||||
}
|
||||
}
|
||||
|
||||
fn start_approval_async<'a>(
|
||||
|
||||
@@ -255,6 +255,19 @@ impl DeveloperInstructions {
|
||||
None => APPROVAL_POLICY_ON_REQUEST_RULE.to_string(),
|
||||
}
|
||||
}
|
||||
AskForApproval::Reject {
|
||||
sandbox_approval,
|
||||
rules,
|
||||
mcp_elicitations,
|
||||
} => {
|
||||
format!(
|
||||
"Approval policy is `reject`.\n\
|
||||
- `sandbox_approval`: {sandbox_approval}\n\
|
||||
- `rules`: {rules}\n\
|
||||
- `mcp_elicitations`: {mcp_elicitations}\n\
|
||||
When a category is `true`, requests in that category are auto-rejected instead of prompting the user."
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
DeveloperInstructions::new(text)
|
||||
|
||||
@@ -377,11 +377,60 @@ pub enum AskForApproval {
|
||||
#[default]
|
||||
OnRequest,
|
||||
|
||||
/// Fine-grained rejection controls for approval prompts.
|
||||
///
|
||||
/// When a field is `true`, prompts of that category are automatically
|
||||
/// rejected instead of shown to the user.
|
||||
Reject {
|
||||
/// Reject approval prompts related to sandbox escalation.
|
||||
sandbox_approval: bool,
|
||||
/// Reject prompts triggered by execpolicy `prompt` rules.
|
||||
rules: bool,
|
||||
/// Reject MCP elicitation prompts.
|
||||
mcp_elicitations: bool,
|
||||
},
|
||||
|
||||
/// Never ask the user to approve commands. Failures are immediately returned
|
||||
/// to the model, and never escalated to the user for approval.
|
||||
Never,
|
||||
}
|
||||
|
||||
impl AskForApproval {
|
||||
/// Backward-compatible defaults for `approval_policy = "reject"` in
|
||||
/// `config.toml`.
|
||||
pub const fn reject_defaults() -> Self {
|
||||
Self::Reject {
|
||||
sandbox_approval: true,
|
||||
rules: false,
|
||||
mcp_elicitations: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn rejects_sandbox_approval(self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::Reject {
|
||||
sandbox_approval: true,
|
||||
..
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
pub const fn rejects_rules_approval(self) -> bool {
|
||||
matches!(self, Self::Reject { rules: true, .. })
|
||||
}
|
||||
|
||||
pub const fn rejects_mcp_elicitations(self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::Reject {
|
||||
mcp_elicitations: true,
|
||||
..
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents whether outbound network access is available to the agent.
|
||||
#[derive(
|
||||
Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Display, Default, JsonSchema, TS,
|
||||
|
||||
Reference in New Issue
Block a user