Revert "Add skill approval event/response (#12633)" (#12811)

This reverts commit https://github.com/openai/codex/pull/12633. We no
longer need this PR, because we favor sending normal exec command
approval server request with `additional_permissions` of skill
permissions instead
This commit is contained in:
Celia Chen 2026-02-25 17:02:42 -08:00 committed by GitHub
parent 4fedef88e0
commit 4f45668106
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 4 additions and 595 deletions

View file

@ -1884,30 +1884,6 @@
"title": "DynamicToolCallResponseEventMsg",
"type": "object"
},
{
"properties": {
"item_id": {
"type": "string"
},
"skill_name": {
"type": "string"
},
"type": {
"enum": [
"skill_request_approval"
],
"title": "SkillRequestApprovalEventMsgType",
"type": "string"
}
},
"required": [
"item_id",
"skill_name",
"type"
],
"title": "SkillRequestApprovalEventMsg",
"type": "object"
},
{
"properties": {
"id": {
@ -7374,30 +7350,6 @@
"title": "DynamicToolCallResponseEventMsg",
"type": "object"
},
{
"properties": {
"item_id": {
"type": "string"
},
"skill_name": {
"type": "string"
},
"type": {
"enum": [
"skill_request_approval"
],
"title": "SkillRequestApprovalEventMsgType",
"type": "string"
}
},
"required": [
"item_id",
"skill_name",
"type"
],
"title": "SkillRequestApprovalEventMsg",
"type": "object"
},
{
"properties": {
"id": {

View file

@ -722,21 +722,6 @@
}
]
},
"SkillRequestApprovalParams": {
"properties": {
"itemId": {
"type": "string"
},
"skillName": {
"type": "string"
}
},
"required": [
"itemId",
"skillName"
],
"type": "object"
},
"ThreadId": {
"type": "string"
},
@ -898,30 +883,6 @@
"title": "Item/tool/requestUserInputRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"skill/requestApproval"
],
"title": "Skill/requestApprovalRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/SkillRequestApprovalParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Skill/requestApprovalRequest",
"type": "object"
},
{
"description": "Execute a dynamic tool call on the client.",
"properties": {

View file

@ -1,17 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"itemId": {
"type": "string"
},
"skillName": {
"type": "string"
}
},
"required": [
"itemId",
"skillName"
],
"title": "SkillRequestApprovalParams",
"type": "object"
}

View file

@ -1,22 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"SkillApprovalDecision": {
"enum": [
"approve",
"decline"
],
"type": "string"
}
},
"properties": {
"decision": {
"$ref": "#/definitions/SkillApprovalDecision"
}
},
"required": [
"decision"
],
"title": "SkillRequestApprovalResponse",
"type": "object"
}

View file

@ -3052,30 +3052,6 @@
"title": "DynamicToolCallResponseEventMsg",
"type": "object"
},
{
"properties": {
"item_id": {
"type": "string"
},
"skill_name": {
"type": "string"
},
"type": {
"enum": [
"skill_request_approval"
],
"title": "SkillRequestApprovalEventMsgType",
"type": "string"
}
},
"required": [
"item_id",
"skill_name",
"type"
],
"title": "SkillRequestApprovalEventMsg",
"type": "object"
},
{
"properties": {
"id": {
@ -6732,30 +6708,6 @@
"title": "Item/tool/requestUserInputRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"skill/requestApproval"
],
"title": "Skill/requestApprovalRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/SkillRequestApprovalParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Skill/requestApprovalRequest",
"type": "object"
},
{
"description": "Execute a dynamic tool call on the client.",
"properties": {
@ -6877,43 +6829,6 @@
],
"type": "object"
},
"SkillApprovalDecision": {
"enum": [
"approve",
"decline"
],
"type": "string"
},
"SkillRequestApprovalParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"itemId": {
"type": "string"
},
"skillName": {
"type": "string"
}
},
"required": [
"itemId",
"skillName"
],
"title": "SkillRequestApprovalParams",
"type": "object"
},
"SkillRequestApprovalResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"decision": {
"$ref": "#/definitions/SkillApprovalDecision"
}
},
"required": [
"decision"
],
"title": "SkillRequestApprovalResponse",
"type": "object"
},
"StepStatus": {
"enum": [
"pending",

View file

@ -57,7 +57,6 @@ import type { RemoteSkillDownloadedEvent } from "./RemoteSkillDownloadedEvent";
import type { RequestUserInputEvent } from "./RequestUserInputEvent";
import type { ReviewRequest } from "./ReviewRequest";
import type { SessionConfiguredEvent } from "./SessionConfiguredEvent";
import type { SkillRequestApprovalEvent } from "./SkillRequestApprovalEvent";
import type { StreamErrorEvent } from "./StreamErrorEvent";
import type { TerminalInteractionEvent } from "./TerminalInteractionEvent";
import type { ThreadNameUpdatedEvent } from "./ThreadNameUpdatedEvent";
@ -80,4 +79,4 @@ import type { WebSearchEndEvent } from "./WebSearchEndEvent";
* Response event from the agent
* NOTE: Make sure none of these values have optional types, as it will mess up the extension code-gen.
*/
export type EventMsg = { "type": "error" } & ErrorEvent | { "type": "warning" } & WarningEvent | { "type": "realtime_conversation_started" } & RealtimeConversationStartedEvent | { "type": "realtime_conversation_realtime" } & RealtimeConversationRealtimeEvent | { "type": "realtime_conversation_closed" } & RealtimeConversationClosedEvent | { "type": "model_reroute" } & ModelRerouteEvent | { "type": "context_compacted" } & ContextCompactedEvent | { "type": "thread_rolled_back" } & ThreadRolledBackEvent | { "type": "task_started" } & TurnStartedEvent | { "type": "task_complete" } & TurnCompleteEvent | { "type": "token_count" } & TokenCountEvent | { "type": "agent_message" } & AgentMessageEvent | { "type": "user_message" } & UserMessageEvent | { "type": "agent_message_delta" } & AgentMessageDeltaEvent | { "type": "agent_reasoning" } & AgentReasoningEvent | { "type": "agent_reasoning_delta" } & AgentReasoningDeltaEvent | { "type": "agent_reasoning_raw_content" } & AgentReasoningRawContentEvent | { "type": "agent_reasoning_raw_content_delta" } & AgentReasoningRawContentDeltaEvent | { "type": "agent_reasoning_section_break" } & AgentReasoningSectionBreakEvent | { "type": "session_configured" } & SessionConfiguredEvent | { "type": "thread_name_updated" } & ThreadNameUpdatedEvent | { "type": "mcp_startup_update" } & McpStartupUpdateEvent | { "type": "mcp_startup_complete" } & McpStartupCompleteEvent | { "type": "mcp_tool_call_begin" } & McpToolCallBeginEvent | { "type": "mcp_tool_call_end" } & McpToolCallEndEvent | { "type": "web_search_begin" } & WebSearchBeginEvent | { "type": "web_search_end" } & WebSearchEndEvent | { "type": "exec_command_begin" } & ExecCommandBeginEvent | { "type": "exec_command_output_delta" } & ExecCommandOutputDeltaEvent | { "type": "terminal_interaction" } & TerminalInteractionEvent | { "type": "exec_command_end" } & ExecCommandEndEvent | { "type": "view_image_tool_call" } & ViewImageToolCallEvent | { "type": "exec_approval_request" } & ExecApprovalRequestEvent | { "type": "request_user_input" } & RequestUserInputEvent | { "type": "dynamic_tool_call_request" } & DynamicToolCallRequest | { "type": "dynamic_tool_call_response" } & DynamicToolCallResponseEvent | { "type": "skill_request_approval" } & SkillRequestApprovalEvent | { "type": "elicitation_request" } & ElicitationRequestEvent | { "type": "apply_patch_approval_request" } & ApplyPatchApprovalRequestEvent | { "type": "deprecation_notice" } & DeprecationNoticeEvent | { "type": "background_event" } & BackgroundEventEvent | { "type": "undo_started" } & UndoStartedEvent | { "type": "undo_completed" } & UndoCompletedEvent | { "type": "stream_error" } & StreamErrorEvent | { "type": "patch_apply_begin" } & PatchApplyBeginEvent | { "type": "patch_apply_end" } & PatchApplyEndEvent | { "type": "turn_diff" } & TurnDiffEvent | { "type": "get_history_entry_response" } & GetHistoryEntryResponseEvent | { "type": "mcp_list_tools_response" } & McpListToolsResponseEvent | { "type": "list_custom_prompts_response" } & ListCustomPromptsResponseEvent | { "type": "list_skills_response" } & ListSkillsResponseEvent | { "type": "list_remote_skills_response" } & ListRemoteSkillsResponseEvent | { "type": "remote_skill_downloaded" } & RemoteSkillDownloadedEvent | { "type": "skills_update_available" } | { "type": "plan_update" } & UpdatePlanArgs | { "type": "turn_aborted" } & TurnAbortedEvent | { "type": "shutdown_complete" } | { "type": "entered_review_mode" } & ReviewRequest | { "type": "exited_review_mode" } & ExitedReviewModeEvent | { "type": "raw_response_item" } & RawResponseItemEvent | { "type": "item_started" } & ItemStartedEvent | { "type": "item_completed" } & ItemCompletedEvent | { "type": "agent_message_content_delta" } & AgentMessageContentDeltaEvent | { "type": "plan_delta" } & PlanDeltaEvent | { "type": "reasoning_content_delta" } & ReasoningContentDeltaEvent | { "type": "reasoning_raw_content_delta" } & ReasoningRawContentDeltaEvent | { "type": "collab_agent_spawn_begin" } & CollabAgentSpawnBeginEvent | { "type": "collab_agent_spawn_end" } & CollabAgentSpawnEndEvent | { "type": "collab_agent_interaction_begin" } & CollabAgentInteractionBeginEvent | { "type": "collab_agent_interaction_end" } & CollabAgentInteractionEndEvent | { "type": "collab_waiting_begin" } & CollabWaitingBeginEvent | { "type": "collab_waiting_end" } & CollabWaitingEndEvent | { "type": "collab_close_begin" } & CollabCloseBeginEvent | { "type": "collab_close_end" } & CollabCloseEndEvent | { "type": "collab_resume_begin" } & CollabResumeBeginEvent | { "type": "collab_resume_end" } & CollabResumeEndEvent;
export type EventMsg = { "type": "error" } & ErrorEvent | { "type": "warning" } & WarningEvent | { "type": "realtime_conversation_started" } & RealtimeConversationStartedEvent | { "type": "realtime_conversation_realtime" } & RealtimeConversationRealtimeEvent | { "type": "realtime_conversation_closed" } & RealtimeConversationClosedEvent | { "type": "model_reroute" } & ModelRerouteEvent | { "type": "context_compacted" } & ContextCompactedEvent | { "type": "thread_rolled_back" } & ThreadRolledBackEvent | { "type": "task_started" } & TurnStartedEvent | { "type": "task_complete" } & TurnCompleteEvent | { "type": "token_count" } & TokenCountEvent | { "type": "agent_message" } & AgentMessageEvent | { "type": "user_message" } & UserMessageEvent | { "type": "agent_message_delta" } & AgentMessageDeltaEvent | { "type": "agent_reasoning" } & AgentReasoningEvent | { "type": "agent_reasoning_delta" } & AgentReasoningDeltaEvent | { "type": "agent_reasoning_raw_content" } & AgentReasoningRawContentEvent | { "type": "agent_reasoning_raw_content_delta" } & AgentReasoningRawContentDeltaEvent | { "type": "agent_reasoning_section_break" } & AgentReasoningSectionBreakEvent | { "type": "session_configured" } & SessionConfiguredEvent | { "type": "thread_name_updated" } & ThreadNameUpdatedEvent | { "type": "mcp_startup_update" } & McpStartupUpdateEvent | { "type": "mcp_startup_complete" } & McpStartupCompleteEvent | { "type": "mcp_tool_call_begin" } & McpToolCallBeginEvent | { "type": "mcp_tool_call_end" } & McpToolCallEndEvent | { "type": "web_search_begin" } & WebSearchBeginEvent | { "type": "web_search_end" } & WebSearchEndEvent | { "type": "exec_command_begin" } & ExecCommandBeginEvent | { "type": "exec_command_output_delta" } & ExecCommandOutputDeltaEvent | { "type": "terminal_interaction" } & TerminalInteractionEvent | { "type": "exec_command_end" } & ExecCommandEndEvent | { "type": "view_image_tool_call" } & ViewImageToolCallEvent | { "type": "exec_approval_request" } & ExecApprovalRequestEvent | { "type": "request_user_input" } & RequestUserInputEvent | { "type": "dynamic_tool_call_request" } & DynamicToolCallRequest | { "type": "dynamic_tool_call_response" } & DynamicToolCallResponseEvent | { "type": "elicitation_request" } & ElicitationRequestEvent | { "type": "apply_patch_approval_request" } & ApplyPatchApprovalRequestEvent | { "type": "deprecation_notice" } & DeprecationNoticeEvent | { "type": "background_event" } & BackgroundEventEvent | { "type": "undo_started" } & UndoStartedEvent | { "type": "undo_completed" } & UndoCompletedEvent | { "type": "stream_error" } & StreamErrorEvent | { "type": "patch_apply_begin" } & PatchApplyBeginEvent | { "type": "patch_apply_end" } & PatchApplyEndEvent | { "type": "turn_diff" } & TurnDiffEvent | { "type": "get_history_entry_response" } & GetHistoryEntryResponseEvent | { "type": "mcp_list_tools_response" } & McpListToolsResponseEvent | { "type": "list_custom_prompts_response" } & ListCustomPromptsResponseEvent | { "type": "list_skills_response" } & ListSkillsResponseEvent | { "type": "list_remote_skills_response" } & ListRemoteSkillsResponseEvent | { "type": "remote_skill_downloaded" } & RemoteSkillDownloadedEvent | { "type": "skills_update_available" } | { "type": "plan_update" } & UpdatePlanArgs | { "type": "turn_aborted" } & TurnAbortedEvent | { "type": "shutdown_complete" } | { "type": "entered_review_mode" } & ReviewRequest | { "type": "exited_review_mode" } & ExitedReviewModeEvent | { "type": "raw_response_item" } & RawResponseItemEvent | { "type": "item_started" } & ItemStartedEvent | { "type": "item_completed" } & ItemCompletedEvent | { "type": "agent_message_content_delta" } & AgentMessageContentDeltaEvent | { "type": "plan_delta" } & PlanDeltaEvent | { "type": "reasoning_content_delta" } & ReasoningContentDeltaEvent | { "type": "reasoning_raw_content_delta" } & ReasoningRawContentDeltaEvent | { "type": "collab_agent_spawn_begin" } & CollabAgentSpawnBeginEvent | { "type": "collab_agent_spawn_end" } & CollabAgentSpawnEndEvent | { "type": "collab_agent_interaction_begin" } & CollabAgentInteractionBeginEvent | { "type": "collab_agent_interaction_end" } & CollabAgentInteractionEndEvent | { "type": "collab_waiting_begin" } & CollabWaitingBeginEvent | { "type": "collab_waiting_end" } & CollabWaitingEndEvent | { "type": "collab_close_begin" } & CollabCloseBeginEvent | { "type": "collab_close_end" } & CollabCloseEndEvent | { "type": "collab_resume_begin" } & CollabResumeBeginEvent | { "type": "collab_resume_end" } & CollabResumeEndEvent;

View file

@ -8,10 +8,9 @@ import type { ChatgptAuthTokensRefreshParams } from "./v2/ChatgptAuthTokensRefre
import type { CommandExecutionRequestApprovalParams } from "./v2/CommandExecutionRequestApprovalParams";
import type { DynamicToolCallParams } from "./v2/DynamicToolCallParams";
import type { FileChangeRequestApprovalParams } from "./v2/FileChangeRequestApprovalParams";
import type { SkillRequestApprovalParams } from "./v2/SkillRequestApprovalParams";
import type { ToolRequestUserInputParams } from "./v2/ToolRequestUserInputParams";
/**
* Request initiated from the server and sent to the client.
*/
export type ServerRequest = { "method": "item/commandExecution/requestApproval", id: RequestId, params: CommandExecutionRequestApprovalParams, } | { "method": "item/fileChange/requestApproval", id: RequestId, params: FileChangeRequestApprovalParams, } | { "method": "item/tool/requestUserInput", id: RequestId, params: ToolRequestUserInputParams, } | { "method": "skill/requestApproval", id: RequestId, params: SkillRequestApprovalParams, } | { "method": "item/tool/call", id: RequestId, params: DynamicToolCallParams, } | { "method": "account/chatgptAuthTokens/refresh", id: RequestId, params: ChatgptAuthTokensRefreshParams, } | { "method": "applyPatchApproval", id: RequestId, params: ApplyPatchApprovalParams, } | { "method": "execCommandApproval", id: RequestId, params: ExecCommandApprovalParams, };
export type ServerRequest = { "method": "item/commandExecution/requestApproval", id: RequestId, params: CommandExecutionRequestApprovalParams, } | { "method": "item/fileChange/requestApproval", id: RequestId, params: FileChangeRequestApprovalParams, } | { "method": "item/tool/requestUserInput", id: RequestId, params: ToolRequestUserInputParams, } | { "method": "item/tool/call", id: RequestId, params: DynamicToolCallParams, } | { "method": "account/chatgptAuthTokens/refresh", id: RequestId, params: ChatgptAuthTokensRefreshParams, } | { "method": "applyPatchApproval", id: RequestId, params: ApplyPatchApprovalParams, } | { "method": "execCommandApproval", id: RequestId, params: ExecCommandApprovalParams, };

View file

@ -1,5 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type SkillRequestApprovalEvent = { item_id: string, skill_name: string, };

View file

@ -209,7 +209,6 @@ export type { SkillDependencies } from "./SkillDependencies";
export type { SkillErrorInfo } from "./SkillErrorInfo";
export type { SkillInterface } from "./SkillInterface";
export type { SkillMetadata } from "./SkillMetadata";
export type { SkillRequestApprovalEvent } from "./SkillRequestApprovalEvent";
export type { SkillScope } from "./SkillScope";
export type { SkillToolDependency } from "./SkillToolDependency";
export type { SkillsListEntry } from "./SkillsListEntry";

View file

@ -1,5 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type SkillApprovalDecision = "approve" | "decline";

View file

@ -1,5 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type SkillRequestApprovalParams = { itemId: string, skillName: string, };

View file

@ -1,6 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { SkillApprovalDecision } from "./SkillApprovalDecision";
export type SkillRequestApprovalResponse = { decision: SkillApprovalDecision, };

View file

@ -141,13 +141,10 @@ export type { SandboxMode } from "./SandboxMode";
export type { SandboxPolicy } from "./SandboxPolicy";
export type { SandboxWorkspaceWrite } from "./SandboxWorkspaceWrite";
export type { SessionSource } from "./SessionSource";
export type { SkillApprovalDecision } from "./SkillApprovalDecision";
export type { SkillDependencies } from "./SkillDependencies";
export type { SkillErrorInfo } from "./SkillErrorInfo";
export type { SkillInterface } from "./SkillInterface";
export type { SkillMetadata } from "./SkillMetadata";
export type { SkillRequestApprovalParams } from "./SkillRequestApprovalParams";
export type { SkillRequestApprovalResponse } from "./SkillRequestApprovalResponse";
export type { SkillScope } from "./SkillScope";
export type { SkillToolDependency } from "./SkillToolDependency";
export type { SkillsConfigWriteParams } from "./SkillsConfigWriteParams";

View file

@ -715,11 +715,6 @@ server_request_definitions! {
response: v2::ToolRequestUserInputResponse,
},
SkillRequestApproval => "skill/requestApproval" {
params: v2::SkillRequestApprovalParams,
response: v2::SkillRequestApprovalResponse,
},
/// Execute a dynamic tool call on the client.
DynamicToolCall => "item/tool/call" {
params: v2::DynamicToolCallParams,

View file

@ -3842,29 +3842,6 @@ pub struct FileChangeRequestApprovalResponse {
pub decision: FileChangeApprovalDecision,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS, ExperimentalApi)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct SkillRequestApprovalParams {
pub item_id: String,
pub skill_name: String,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub enum SkillApprovalDecision {
Approve,
Decline,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct SkillRequestApprovalResponse {
pub decision: SkillApprovalDecision,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]

View file

@ -57,9 +57,6 @@ use codex_app_server_protocol::SendUserMessageParams;
use codex_app_server_protocol::SendUserMessageResponse;
use codex_app_server_protocol::ServerNotification;
use codex_app_server_protocol::ServerRequest;
use codex_app_server_protocol::SkillApprovalDecision;
use codex_app_server_protocol::SkillRequestApprovalParams;
use codex_app_server_protocol::SkillRequestApprovalResponse;
use codex_app_server_protocol::ThreadItem;
use codex_app_server_protocol::ThreadListParams;
use codex_app_server_protocol::ThreadListResponse;
@ -1511,9 +1508,6 @@ impl CodexClient {
ServerRequest::FileChangeRequestApproval { request_id, params } => {
self.approve_file_change_request(request_id, params)?;
}
ServerRequest::SkillRequestApproval { request_id, params } => {
self.approve_skill_request(request_id, params)?;
}
other => {
bail!("received unsupported server request: {other:?}");
}
@ -1593,22 +1587,6 @@ impl CodexClient {
Ok(())
}
fn approve_skill_request(
&mut self,
request_id: RequestId,
params: SkillRequestApprovalParams,
) -> Result<()> {
println!(
"\n< skill approval requested for item {}, skill {}",
params.item_id, params.skill_name
);
let response = SkillRequestApprovalResponse {
decision: SkillApprovalDecision::Approve,
};
self.send_server_request_response(request_id, &response)?;
Ok(())
}
fn approve_file_change_request(
&mut self,
request_id: RequestId,

View file

@ -58,9 +58,6 @@ use codex_app_server_protocol::ReasoningSummaryTextDeltaNotification;
use codex_app_server_protocol::ReasoningTextDeltaNotification;
use codex_app_server_protocol::ServerNotification;
use codex_app_server_protocol::ServerRequestPayload;
use codex_app_server_protocol::SkillApprovalDecision as V2SkillApprovalDecision;
use codex_app_server_protocol::SkillRequestApprovalParams;
use codex_app_server_protocol::SkillRequestApprovalResponse;
use codex_app_server_protocol::TerminalInteractionNotification;
use codex_app_server_protocol::ThreadItem;
use codex_app_server_protocol::ThreadNameUpdatedNotification;
@ -111,7 +108,6 @@ use codex_protocol::protocol::TokenCountEvent;
use codex_protocol::protocol::TurnDiffEvent;
use codex_protocol::request_user_input::RequestUserInputAnswer as CoreRequestUserInputAnswer;
use codex_protocol::request_user_input::RequestUserInputResponse as CoreRequestUserInputResponse;
use codex_protocol::skill_approval::SkillApprovalResponse as CoreSkillApprovalResponse;
use codex_shell_command::parse_command::shlex_join;
use std::collections::HashMap;
use std::convert::TryFrom;
@ -518,37 +514,6 @@ pub(crate) async fn apply_bespoke_event_handling(
}
}
}
EventMsg::SkillRequestApproval(request) => {
if matches!(api_version, ApiVersion::V2) {
let item_id = request.item_id;
let skill_name = request.skill_name;
let params = SkillRequestApprovalParams {
item_id: item_id.clone(),
skill_name,
};
let rx = outgoing
.send_request(ServerRequestPayload::SkillRequestApproval(params))
.await;
tokio::spawn(async move {
let approved = match rx.await {
Ok(Ok(value)) => {
serde_json::from_value::<SkillRequestApprovalResponse>(value)
.map(|response| {
matches!(response.decision, V2SkillApprovalDecision::Approve)
})
.unwrap_or(false)
}
_ => false,
};
let _ = conversation
.submit(Op::SkillApproval {
id: item_id,
response: CoreSkillApprovalResponse { approved },
})
.await;
});
}
}
EventMsg::DynamicToolCallRequest(request) => {
if matches!(api_version, ApiVersion::V2) {
let call_id = request.call_id;

View file

@ -19,7 +19,6 @@ mod realtime_conversation;
mod request_user_input;
mod review;
mod safety_check_downgrade;
mod skill_approval;
mod skills_list;
mod thread_archive;
mod thread_fork;

View file

@ -1,109 +0,0 @@
use anyhow::Result;
use app_test_support::McpProcess;
use app_test_support::create_final_assistant_message_sse_response;
use app_test_support::create_mock_responses_server_sequence;
use app_test_support::to_response;
use codex_app_server_protocol::JSONRPCResponse;
use codex_app_server_protocol::RequestId;
use codex_app_server_protocol::ServerRequest;
use codex_app_server_protocol::ThreadStartParams;
use codex_app_server_protocol::ThreadStartResponse;
use codex_app_server_protocol::TurnStartParams;
use codex_app_server_protocol::TurnStartResponse;
use codex_app_server_protocol::UserInput as V2UserInput;
use tokio::time::timeout;
const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn skill_request_approval_round_trip() -> Result<()> {
let codex_home = tempfile::TempDir::new()?;
let server =
create_mock_responses_server_sequence(vec![create_final_assistant_message_sse_response(
"done",
)?])
.await;
create_config_toml(codex_home.path(), &server.uri())?;
let mut mcp = McpProcess::new(codex_home.path()).await?;
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
let thread_start_id = mcp
.send_thread_start_request(ThreadStartParams {
model: Some("mock-model".to_string()),
..Default::default()
})
.await?;
let thread_start_resp: JSONRPCResponse = timeout(
DEFAULT_READ_TIMEOUT,
mcp.read_stream_until_response_message(RequestId::Integer(thread_start_id)),
)
.await??;
let ThreadStartResponse { thread, .. } = to_response(thread_start_resp)?;
let turn_start_id = mcp
.send_turn_start_request(TurnStartParams {
thread_id: thread.id.clone(),
input: vec![V2UserInput::Text {
text: "ask something".to_string(),
text_elements: Vec::new(),
}],
model: Some("mock-model".to_string()),
..Default::default()
})
.await?;
let turn_start_resp: JSONRPCResponse = timeout(
DEFAULT_READ_TIMEOUT,
mcp.read_stream_until_response_message(RequestId::Integer(turn_start_id)),
)
.await??;
let TurnStartResponse { turn, .. } = to_response(turn_start_resp)?;
let server_req = timeout(
DEFAULT_READ_TIMEOUT,
mcp.read_stream_until_request_message(),
)
.await??;
let ServerRequest::SkillRequestApproval { request_id, params } = server_req else {
panic!("expected SkillRequestApproval request, got: {server_req:?}");
};
assert_eq!(params.item_id, turn.id);
assert_eq!(params.skill_name, "test-skill");
mcp.send_response(request_id, serde_json::json!({ "decision": "approve" }))
.await?;
timeout(
DEFAULT_READ_TIMEOUT,
mcp.read_stream_until_notification_message("turn/completed"),
)
.await??;
Ok(())
}
fn create_config_toml(codex_home: &std::path::Path, server_uri: &str) -> std::io::Result<()> {
let config_toml = codex_home.join("config.toml");
std::fs::write(
config_toml,
format!(
r#"
model = "mock-model"
approval_policy = "never"
sandbox_mode = "read-only"
model_provider = "mock_provider"
[features]
skill_approval = true
[model_providers.mock_provider]
name = "Mock provider for test"
base_url = "{server_uri}/v1"
request_max_retries = 0
stream_max_retries = 0
"#
),
)
}

View file

@ -409,9 +409,6 @@
"shell_zsh_fork": {
"type": "boolean"
},
"skill_approval": {
"type": "boolean"
},
"skill_env_var_dependency_prompt": {
"type": "boolean"
},
@ -1705,9 +1702,6 @@
"shell_zsh_fork": {
"type": "boolean"
},
"skill_approval": {
"type": "boolean"
},
"skill_env_var_dependency_prompt": {
"type": "boolean"
},

View file

@ -94,7 +94,6 @@ use codex_protocol::protocol::TurnContextNetworkItem;
use codex_protocol::protocol::TurnStartedEvent;
use codex_protocol::request_user_input::RequestUserInputArgs;
use codex_protocol::request_user_input::RequestUserInputResponse;
use codex_protocol::skill_approval::SkillApprovalResponse;
use codex_rmcp_client::ElicitationResponse;
use codex_rmcp_client::OAuthCredentialsStoreMode;
use codex_utils_stream_parser::AssistantTextChunk;
@ -2723,40 +2722,6 @@ impl Session {
rx_response.await.ok()
}
pub async fn request_skill_approval(
&self,
turn_context: &TurnContext,
item_id: String,
skill_name: String,
) -> Option<SkillApprovalResponse> {
let (tx_response, rx_response) = oneshot::channel();
let prev_entry = {
let mut active = self.active_turn.lock().await;
match active.as_mut() {
Some(at) => {
let mut ts = at.turn_state.lock().await;
ts.insert_pending_skill_approval(item_id.clone(), tx_response)
}
None => None,
}
};
if prev_entry.is_some() {
warn!("Overwriting existing pending skill approval for item_id: {item_id}");
}
self.send_event(
turn_context,
EventMsg::SkillRequestApproval(
codex_protocol::skill_approval::SkillRequestApprovalEvent {
item_id,
skill_name,
},
),
)
.await;
rx_response.await.ok()
}
pub async fn notify_user_input_response(
&self,
sub_id: &str,
@ -2803,31 +2768,6 @@ impl Session {
}
}
pub async fn notify_skill_approval_response(
&self,
item_id: &str,
response: SkillApprovalResponse,
) {
let entry = {
let mut active = self.active_turn.lock().await;
match active.as_mut() {
Some(at) => {
let mut ts = at.turn_state.lock().await;
ts.remove_pending_skill_approval(item_id)
}
None => None,
}
};
match entry {
Some(tx_response) => {
tx_response.send(response).ok();
}
None => {
warn!("No pending skill approval found for item_id: {item_id}");
}
}
}
pub async fn notify_approval(&self, approval_id: &str, decision: ReviewDecision) {
let entry = {
let mut active = self.active_turn.lock().await;
@ -3731,9 +3671,6 @@ async fn submission_loop(sess: Arc<Session>, config: Arc<Config>, rx_sub: Receiv
Op::DynamicToolResponse { id, response } => {
handlers::dynamic_tool_response(&sess, id, response).await;
}
Op::SkillApproval { id, response } => {
handlers::skill_approval_response(&sess, id, response).await;
}
Op::AddToHistory { text } => {
handlers::add_to_history(&sess, &config, text).await;
}
@ -3857,7 +3794,6 @@ mod handlers {
use codex_protocol::protocol::TurnAbortReason;
use codex_protocol::protocol::WarningEvent;
use codex_protocol::request_user_input::RequestUserInputResponse;
use codex_protocol::skill_approval::SkillApprovalResponse;
use crate::context_manager::is_user_turn_boundary;
use codex_protocol::config_types::CollaborationMode;
@ -4098,14 +4034,6 @@ mod handlers {
sess.notify_dynamic_tool_response(&id, response).await;
}
pub async fn skill_approval_response(
sess: &Arc<Session>,
id: String,
response: SkillApprovalResponse,
) {
sess.notify_skill_approval_response(&id, response).await;
}
pub async fn add_to_history(sess: &Arc<Session>, config: &Arc<Config>, text: String) {
let id = sess.conversation_id;
let config = Arc::clone(config);
@ -4819,15 +4747,6 @@ pub(crate) async fn run_turn(
collaboration_mode_kind: turn_context.collaboration_mode.mode,
});
sess.send_event(&turn_context, event).await;
if turn_context.config.features.enabled(Feature::SkillApproval) {
let _ = sess
.request_skill_approval(
turn_context.as_ref(),
turn_context.sub_id.clone(),
"test-skill".to_string(),
)
.await;
}
// TODO(ccunningham): Pre-turn compaction runs before context updates and the
// new user message are recorded. Estimate pending incoming items (context
// diffs/full reinjection + user input) and trigger compaction preemptively
@ -5856,7 +5775,6 @@ fn realtime_text_for_event(msg: &EventMsg) -> Option<String> {
| EventMsg::RequestUserInput(_)
| EventMsg::DynamicToolCallRequest(_)
| EventMsg::DynamicToolCallResponse(_)
| EventMsg::SkillRequestApproval(_)
| EventMsg::ElicitationRequest(_)
| EventMsg::ApplyPatchApprovalRequest(_)
| EventMsg::DeprecationNotice(_)

View file

@ -133,8 +133,6 @@ pub enum Feature {
SkillMcpDependencyInstall,
/// Prompt for missing skill env var dependencies.
SkillEnvVarDependencyPrompt,
/// Emit skill approval test prompts/events.
SkillApproval,
/// Steer feature flag - when enabled, Enter submits immediately instead of queuing.
/// Kept for config backward compatibility; behavior is always steer-enabled.
Steer,
@ -630,12 +628,6 @@ pub const FEATURES: &[FeatureSpec] = &[
stage: Stage::UnderDevelopment,
default_enabled: false,
},
FeatureSpec {
id: Feature::SkillApproval,
key: "skill_approval",
stage: Stage::UnderDevelopment,
default_enabled: false,
},
FeatureSpec {
id: Feature::Steer,
key: "steer",

View file

@ -141,7 +141,6 @@ fn event_msg_persistence_mode(ev: &EventMsg) -> Option<EventPersistenceMode> {
| EventMsg::TerminalInteraction(_)
| EventMsg::ExecCommandOutputDelta(_)
| EventMsg::ExecApprovalRequest(_)
| EventMsg::SkillRequestApproval(_)
| EventMsg::RequestUserInput(_)
| EventMsg::ElicitationRequest(_)
| EventMsg::ApplyPatchApprovalRequest(_)

View file

@ -11,7 +11,6 @@ use tokio_util::task::AbortOnDropHandle;
use codex_protocol::dynamic_tools::DynamicToolResponse;
use codex_protocol::models::ResponseInputItem;
use codex_protocol::request_user_input::RequestUserInputResponse;
use codex_protocol::skill_approval::SkillApprovalResponse;
use tokio::sync::oneshot;
use crate::codex::TurnContext;
@ -72,7 +71,6 @@ impl ActiveTurn {
pub(crate) struct TurnState {
pending_approvals: HashMap<String, oneshot::Sender<ReviewDecision>>,
pending_user_input: HashMap<String, oneshot::Sender<RequestUserInputResponse>>,
pending_skill_approvals: HashMap<String, oneshot::Sender<SkillApprovalResponse>>,
pending_dynamic_tools: HashMap<String, oneshot::Sender<DynamicToolResponse>>,
pending_input: Vec<ResponseInputItem>,
}
@ -96,7 +94,6 @@ impl TurnState {
pub(crate) fn clear_pending(&mut self) {
self.pending_approvals.clear();
self.pending_user_input.clear();
self.pending_skill_approvals.clear();
self.pending_dynamic_tools.clear();
self.pending_input.clear();
}
@ -124,21 +121,6 @@ impl TurnState {
self.pending_dynamic_tools.insert(key, tx)
}
pub(crate) fn insert_pending_skill_approval(
&mut self,
key: String,
tx: oneshot::Sender<SkillApprovalResponse>,
) -> Option<oneshot::Sender<SkillApprovalResponse>> {
self.pending_skill_approvals.insert(key, tx)
}
pub(crate) fn remove_pending_skill_approval(
&mut self,
key: &str,
) -> Option<oneshot::Sender<SkillApprovalResponse>> {
self.pending_skill_approvals.remove(key)
}
pub(crate) fn remove_pending_dynamic_tool(
&mut self,
key: &str,

View file

@ -114,7 +114,6 @@ mod seatbelt;
mod shell_command;
mod shell_serialization;
mod shell_snapshot;
mod skill_approval;
mod skills;
mod sqlite_state;
mod stream_error_allows_next_turn;

View file

@ -64,17 +64,6 @@ async fn submit_turn_with_policies(
Ok(())
}
async fn wait_for_turn_complete_without_skill_approval(test: &TestCodex) {
wait_for_event_match(test.codex.as_ref(), |event| match event {
EventMsg::SkillRequestApproval(request) => {
panic!("unexpected skill approval request: {request:?}");
}
EventMsg::TurnComplete(_) => Some(()),
_ => None,
})
.await;
}
fn write_skill_with_shell_script(home: &Path, name: &str, script_name: &str) -> Result<PathBuf> {
use std::os::unix::fs::PermissionsExt;

View file

@ -854,8 +854,7 @@ impl EventProcessor for EventProcessorWithHumanOutput {
| EventMsg::RealtimeConversationRealtime(_)
| EventMsg::RealtimeConversationClosed(_)
| EventMsg::DynamicToolCallRequest(_)
| EventMsg::DynamicToolCallResponse(_)
| EventMsg::SkillRequestApproval(_) => {}
| EventMsg::DynamicToolCallResponse(_) => {}
}
CodexStatus::Running
}

View file

@ -364,7 +364,6 @@ async fn run_codex_tool_session_inner(
| EventMsg::RequestUserInput(_)
| EventMsg::DynamicToolCallRequest(_)
| EventMsg::DynamicToolCallResponse(_)
| EventMsg::SkillRequestApproval(_)
| EventMsg::ContextCompacted(_)
| EventMsg::ModelReroute(_)
| EventMsg::ThreadRolledBack(_)

View file

@ -15,5 +15,4 @@ pub mod parse_command;
pub mod plan_tool;
pub mod protocol;
pub mod request_user_input;
pub mod skill_approval;
pub mod user_input;

View file

@ -41,7 +41,6 @@ use crate::openai_models::ReasoningEffort as ReasoningEffortConfig;
use crate::parse_command::ParsedCommand;
use crate::plan_tool::UpdatePlanArgs;
use crate::request_user_input::RequestUserInputResponse;
use crate::skill_approval::SkillApprovalResponse;
use crate::user_input::UserInput;
use codex_utils_absolute_path::AbsolutePathBuf;
use schemars::JsonSchema;
@ -62,7 +61,6 @@ pub use crate::approvals::NetworkApprovalProtocol;
pub use crate::approvals::NetworkPolicyAmendment;
pub use crate::approvals::NetworkPolicyRuleAction;
pub use crate::request_user_input::RequestUserInputEvent;
pub use crate::skill_approval::SkillRequestApprovalEvent;
/// Open/close tags for special user-input blocks. Used across crates to avoid
/// duplicated hardcoded strings.
@ -296,14 +294,6 @@ pub enum Op {
response: DynamicToolResponse,
},
/// Resolve a skill approval request.
SkillApproval {
/// Item id for the in-flight request.
id: String,
/// User decision.
response: SkillApprovalResponse,
},
/// Append an entry to the persistent cross-session message history.
///
/// Note the entry is not guaranteed to be logged if the user has
@ -1056,8 +1046,6 @@ pub enum EventMsg {
DynamicToolCallResponse(DynamicToolCallResponseEvent),
SkillRequestApproval(SkillRequestApprovalEvent),
ElicitationRequest(ElicitationRequestEvent),
ApplyPatchApprovalRequest(ApplyPatchApprovalRequestEvent),

View file

@ -1,15 +0,0 @@
use schemars::JsonSchema;
use serde::Deserialize;
use serde::Serialize;
use ts_rs::TS;
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, JsonSchema, TS)]
pub struct SkillRequestApprovalEvent {
pub item_id: String,
pub skill_name: String,
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, JsonSchema, TS)]
pub struct SkillApprovalResponse {
pub approved: bool,
}

View file

@ -4455,8 +4455,7 @@ impl ChatWidget {
| EventMsg::ReasoningContentDelta(_)
| EventMsg::ReasoningRawContentDelta(_)
| EventMsg::DynamicToolCallRequest(_)
| EventMsg::DynamicToolCallResponse(_)
| EventMsg::SkillRequestApproval(_) => {}
| EventMsg::DynamicToolCallResponse(_) => {}
EventMsg::RealtimeConversationStarted(ev) => {
if !from_replay {
self.on_realtime_conversation_started(ev);