Download codex-rs/app-server-protocol/src/protocol/v2/item.rs from SaylorTwift/codex: direct link, hf CLI and curl.
- Browser
- Download file 64.7 kB
-
https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/app-server-protocol/src/protocol/v2/item.rs
- Command line
-
hf download hf://SaylorTwift/codex/codex-rs/app-server-protocol/src/protocol/v2/item.rs
-
curl -L -o item.rs https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/app-server-protocol/src/protocol/v2/item.rs
64.7 kB
| use super::AdditionalPermissionProfile; | |
| use super::ExecPolicyAmendment; | |
| use super::McpToolCallError; | |
| use super::McpToolCallResult; | |
| use super::NetworkApprovalContext; | |
| use super::NetworkApprovalProtocol; | |
| use super::NetworkPolicyAmendment; | |
| use super::RequestPermissionProfile; | |
| use super::UserInput; | |
| use super::shared::v2_enum_from_core; | |
| use crate::JsonSchema; | |
| use crate::TS; | |
| use crate::protocol::item_builders::CommandExecutionPresentation; | |
| use crate::protocol::item_builders::convert_patch_changes; | |
| use crate::protocol::item_builders::review_output_text; | |
| use codex_experimental_api_macros::ExperimentalApi; | |
| use codex_extension_items::ExtensionItem; | |
| pub use codex_extension_items::image_generation::ImageGenerationFailure; | |
| pub use codex_extension_items::image_generation::ImageGenerationItem; | |
| pub use codex_extension_items::sleep::SleepItem; | |
| pub use codex_extension_items::web_search::WebSearchAction; | |
| pub use codex_extension_items::web_search::WebSearchItem; | |
| use codex_protocol::approvals::ExecApprovalKind as CoreExecApprovalKind; | |
| use codex_protocol::approvals::GuardianAssessmentAction as CoreGuardianAssessmentAction; | |
| use codex_protocol::approvals::GuardianAssessmentDecisionSource as CoreGuardianAssessmentDecisionSource; | |
| use codex_protocol::approvals::GuardianCommandSource as CoreGuardianCommandSource; | |
| use codex_protocol::items::AgentMessageContent as CoreAgentMessageContent; | |
| pub use codex_protocol::items::AgentMessageDelivery; | |
| pub use codex_protocol::items::AsyncUserInputQuestion; | |
| use codex_protocol::items::CollabAgentTool as CoreCollabAgentTool; | |
| use codex_protocol::items::CollabAgentToolCallStatus as CoreCollabAgentToolCallStatus; | |
| use codex_protocol::items::CommandExecutionStatus as CoreCommandExecutionStatus; | |
| use codex_protocol::items::DynamicToolCallStatus as CoreDynamicToolCallStatus; | |
| pub use codex_protocol::items::McpAppDisplayMode; | |
| pub use codex_protocol::items::McpAppUi; | |
| use codex_protocol::items::McpToolCallStatus as CoreMcpToolCallStatus; | |
| use codex_protocol::items::TurnItem as CoreTurnItem; | |
| use codex_protocol::memory_citation::MemoryCitation as CoreMemoryCitation; | |
| use codex_protocol::memory_citation::MemoryCitationEntry as CoreMemoryCitationEntry; | |
| use codex_protocol::models::FunctionCallOutputBody; | |
| use codex_protocol::models::MessagePhase; | |
| use codex_protocol::models::ResponseItem; | |
| use codex_protocol::openai_models::ReasoningEffort; | |
| use codex_protocol::parse_command::ParsedCommand as CoreParsedCommand; | |
| use codex_protocol::protocol::AgentStatus as CoreAgentStatus; | |
| use codex_protocol::protocol::ExecCommandSource as CoreExecCommandSource; | |
| use codex_protocol::protocol::ExecCommandStatus as CoreExecCommandStatus; | |
| use codex_protocol::protocol::GuardianRiskLevel as CoreGuardianRiskLevel; | |
| use codex_protocol::protocol::GuardianUserAuthorization as CoreGuardianUserAuthorization; | |
| use codex_protocol::protocol::PatchApplyStatus as CorePatchApplyStatus; | |
| use codex_protocol::protocol::ReviewDecision as CoreReviewDecision; | |
| use codex_protocol::protocol::SubAgentActivityKind as CoreSubAgentActivityKind; | |
| use codex_utils_absolute_path::AbsolutePathBuf; | |
| use codex_utils_path_uri::LegacyAppPathString; | |
| use serde::Deserialize; | |
| use serde::Serialize; | |
| use serde_json::Value as JsonValue; | |
| use serde_with::serde_as; | |
| use std::collections::HashMap; | |
| use std::io; | |
| use std::path::PathBuf; | |
| pub enum CommandExecutionApprovalDecision { | |
| /// User approved the command. | |
| Accept, | |
| /// User approved the command and future prompts in the same session-scoped | |
| /// approval cache should run without prompting. | |
| AcceptForSession, | |
| /// User approved the command, and wants to apply the proposed execpolicy amendment so future | |
| /// matching commands can run without prompting. | |
| AcceptWithExecpolicyAmendment { | |
| execpolicy_amendment: ExecPolicyAmendment, | |
| }, | |
| /// User chose a persistent network policy rule (allow/deny) for this host. | |
| ApplyNetworkPolicyAmendment { | |
| network_policy_amendment: NetworkPolicyAmendment, | |
| }, | |
| /// User denied the command. The agent will continue the turn. | |
| Decline, | |
| /// User denied the command. The turn will also be immediately interrupted. | |
| Cancel, | |
| } | |
| impl From<CoreReviewDecision> for CommandExecutionApprovalDecision { | |
| fn from(value: CoreReviewDecision) -> Self { | |
| match value { | |
| CoreReviewDecision::Approved => Self::Accept, | |
| // MCP approvals are handled through elicitations, so an MCP policy amendment should | |
| // never appear in a command execution approval. To be cautious here, we fail closed. | |
| CoreReviewDecision::ApprovedMcpPolicyAmendment => Self::Decline, | |
| CoreReviewDecision::ApprovedExecpolicyAmendment { | |
| proposed_execpolicy_amendment, | |
| } => Self::AcceptWithExecpolicyAmendment { | |
| execpolicy_amendment: proposed_execpolicy_amendment.into(), | |
| }, | |
| CoreReviewDecision::ApprovedForSession => Self::AcceptForSession, | |
| CoreReviewDecision::NetworkPolicyAmendment { | |
| network_policy_amendment, | |
| } => Self::ApplyNetworkPolicyAmendment { | |
| network_policy_amendment: network_policy_amendment.into(), | |
| }, | |
| CoreReviewDecision::Abort => Self::Cancel, | |
| CoreReviewDecision::Denied { .. } => Self::Decline, | |
| CoreReviewDecision::TimedOut => Self::Decline, | |
| } | |
| } | |
| } | |
| pub enum FileChangeApprovalDecision { | |
| /// User approved the file changes. | |
| Accept, | |
| /// User approved the file changes and future changes to the same files should run without prompting. | |
| AcceptForSession, | |
| /// User denied the file changes. The agent will continue the turn. | |
| Decline, | |
| /// User denied the file changes. The turn will also be immediately interrupted. | |
| Cancel, | |
| } | |
| pub enum CommandAction { | |
| Read { | |
| command: String, | |
| name: String, | |
| path: LegacyAppPathString, | |
| }, | |
| ListFiles { | |
| command: String, | |
| path: Option<String>, | |
| }, | |
| Search { | |
| command: String, | |
| query: Option<String>, | |
| path: Option<String>, | |
| }, | |
| Unknown { | |
| command: String, | |
| }, | |
| } | |
| pub struct MemoryCitation { | |
| pub entries: Vec<MemoryCitationEntry>, | |
| pub thread_ids: Vec<String>, | |
| } | |
| impl From<CoreMemoryCitation> for MemoryCitation { | |
| fn from(value: CoreMemoryCitation) -> Self { | |
| Self { | |
| entries: value.entries.into_iter().map(Into::into).collect(), | |
| thread_ids: value.rollout_ids, | |
| } | |
| } | |
| } | |
| pub struct MemoryCitationEntry { | |
| pub path: String, | |
| pub line_start: u32, | |
| pub line_end: u32, | |
| pub note: String, | |
| } | |
| impl From<CoreMemoryCitationEntry> for MemoryCitationEntry { | |
| fn from(value: CoreMemoryCitationEntry) -> Self { | |
| Self { | |
| path: value.path, | |
| line_start: value.line_start, | |
| line_end: value.line_end, | |
| note: value.note, | |
| } | |
| } | |
| } | |
| impl CommandAction { | |
| pub fn into_core(self) -> CoreParsedCommand { | |
| match self { | |
| CommandAction::Read { | |
| command: cmd, | |
| name, | |
| path, | |
| } => CoreParsedCommand::Read { | |
| cmd, | |
| name, | |
| path: PathBuf::from(path.into_string()), | |
| }, | |
| CommandAction::ListFiles { command: cmd, path } => { | |
| CoreParsedCommand::ListFiles { cmd, path } | |
| } | |
| CommandAction::Search { | |
| command: cmd, | |
| query, | |
| path, | |
| } => CoreParsedCommand::Search { cmd, query, path }, | |
| CommandAction::Unknown { command: cmd } => CoreParsedCommand::Unknown { cmd }, | |
| } | |
| } | |
| pub fn from_core_with_cwd(value: CoreParsedCommand, cwd: &AbsolutePathBuf) -> Self { | |
| match value { | |
| CoreParsedCommand::Read { cmd, name, path } => CommandAction::Read { | |
| command: cmd, | |
| name, | |
| path: cwd.join(path).into(), | |
| }, | |
| CoreParsedCommand::ListFiles { cmd, path } => { | |
| CommandAction::ListFiles { command: cmd, path } | |
| } | |
| CoreParsedCommand::Search { cmd, query, path } => CommandAction::Search { | |
| command: cmd, | |
| query, | |
| path, | |
| }, | |
| CoreParsedCommand::Unknown { cmd } => CommandAction::Unknown { command: cmd }, | |
| } | |
| } | |
| } | |
| pub enum ThreadItem { | |
| UserMessage { | |
| id: String, | |
| client_id: Option<String>, | |
| content: Vec<UserInput>, | |
| }, | |
| HookPrompt { | |
| id: String, | |
| fragments: Vec<HookPromptFragment>, | |
| }, | |
| AgentMessage { | |
| id: String, | |
| text: String, | |
| phase: Option<MessagePhase>, | |
| memory_citation: Option<MemoryCitation>, | |
| delivery: Option<AgentMessageDelivery>, | |
| questions: Option<Vec<AsyncUserInputQuestion>>, | |
| }, | |
| FunctionCallOutput { | |
| id: String, | |
| name: String, | |
| namespace: Option<String>, | |
| output: FunctionCallOutputBody, | |
| }, | |
| /// EXPERIMENTAL - proposed plan item content. The completed plan item is | |
| /// authoritative and may not match the concatenation of `PlanDelta` text. | |
| Plan { | |
| id: String, | |
| text: String, | |
| }, | |
| Reasoning { | |
| id: String, | |
| summary: Vec<String>, | |
| content: Vec<String>, | |
| }, | |
| CommandExecution { | |
| model_context: Option<codex_protocol::items::ModelInvocationContext>, | |
| id: String, | |
| /// Trusted first-party plugin id when this command resolves to one plugin script. | |
| plugin_id: Option<String>, | |
| /// Safe plugin-relative path when this command resolves to one plugin script. | |
| script_path: Option<String>, | |
| /// The command to be executed. | |
| command: String, | |
| /// The command's working directory. | |
| cwd: LegacyAppPathString, | |
| /// Identifier for the underlying PTY process (when available). | |
| process_id: Option<String>, | |
| source: CommandExecutionSource, | |
| status: CommandExecutionStatus, | |
| /// A best-effort parsing of the command to understand the action(s) it will perform. | |
| /// This returns a list of CommandAction objects because a single shell command may | |
| /// be composed of many commands piped together. | |
| command_actions: Vec<CommandAction>, | |
| /// The command's output, aggregated from stdout and stderr. | |
| aggregated_output: Option<String>, | |
| /// The command's exit code. | |
| exit_code: Option<i32>, | |
| /// The duration of the command execution in milliseconds. | |
| duration_ms: Option<i64>, | |
| }, | |
| FileChange { | |
| id: String, | |
| changes: Vec<FileUpdateChange>, | |
| status: PatchApplyStatus, | |
| }, | |
| McpToolCall { | |
| id: String, | |
| server: String, | |
| tool: String, | |
| status: McpToolCallStatus, | |
| arguments: JsonValue, | |
| app_context: Option<McpToolCallAppContext>, | |
| /// Legacy compatibility field; prefer `mcpAppUi.resourceUri` when available. | |
| mcp_app_resource_uri: Option<String>, | |
| /// Presentation captured from the invoked descriptor; absent in older history. | |
| mcp_app_ui: Option<McpAppUi>, | |
| plugin_id: Option<String>, | |
| read_only_hint: Option<bool>, | |
| result: Option<Box<McpToolCallResult>>, | |
| error: Option<McpToolCallError>, | |
| /// The duration of the MCP tool call in milliseconds. | |
| duration_ms: Option<i64>, | |
| }, | |
| DynamicToolCall { | |
| id: String, | |
| namespace: Option<String>, | |
| tool: String, | |
| arguments: JsonValue, | |
| status: DynamicToolCallStatus, | |
| content_items: Option<Vec<DynamicToolCallOutputContentItem>>, | |
| success: Option<bool>, | |
| /// The duration of the dynamic tool call in milliseconds. | |
| duration_ms: Option<i64>, | |
| }, | |
| CollabAgentToolCall { | |
| /// Unique identifier for this collab tool call. | |
| id: String, | |
| /// Name of the collab tool that was invoked. | |
| tool: CollabAgentTool, | |
| /// Current status of the collab tool call. | |
| status: CollabAgentToolCallStatus, | |
| /// Thread ID of the agent issuing the collab request. | |
| sender_thread_id: String, | |
| /// Thread ID of the receiving agent, when applicable. In case of spawn operation, | |
| /// this corresponds to the newly spawned agent. | |
| receiver_thread_ids: Vec<String>, | |
| /// Prompt text sent as part of the collab tool call, when available. | |
| prompt: Option<String>, | |
| /// Model requested for the spawned agent, when applicable. | |
| model: Option<String>, | |
| /// Reasoning effort requested for the spawned agent, when applicable. | |
| reasoning_effort: Option<ReasoningEffort>, | |
| /// Last known status of the target agents, when available. | |
| agents_states: HashMap<String, CollabAgentState>, | |
| }, | |
| SubAgentActivity { | |
| id: String, | |
| kind: SubAgentActivityKind, | |
| agent_thread_id: String, | |
| agent_path: String, | |
| }, | |
| WebSearch(WebSearchItem), | |
| ImageView { | |
| id: String, | |
| path: LegacyAppPathString, | |
| }, | |
| Sleep(SleepItem), | |
| ImageGeneration(ImageGenerationItem), | |
| EnteredReviewMode { | |
| id: String, | |
| review: String, | |
| }, | |
| ExitedReviewMode { | |
| id: String, | |
| review: String, | |
| }, | |
| ContextCompaction { | |
| id: String, | |
| }, | |
| } | |
| pub struct McpToolCallAppContext { | |
| pub connector_id: String, | |
| pub link_id: Option<String>, | |
| pub resource_uri: Option<String>, | |
| pub app_name: Option<String>, | |
| pub action_name: Option<String>, | |
| } | |
| pub struct HookPromptFragment { | |
| pub text: String, | |
| pub hook_run_id: String, | |
| } | |
| impl ThreadItem { | |
| pub fn id(&self) -> &str { | |
| match self { | |
| ThreadItem::UserMessage { id, .. } | |
| | ThreadItem::HookPrompt { id, .. } | |
| | ThreadItem::AgentMessage { id, .. } | |
| | ThreadItem::FunctionCallOutput { id, .. } | |
| | ThreadItem::Plan { id, .. } | |
| | ThreadItem::Reasoning { id, .. } | |
| | ThreadItem::CommandExecution { id, .. } | |
| | ThreadItem::FileChange { id, .. } | |
| | ThreadItem::McpToolCall { id, .. } | |
| | ThreadItem::DynamicToolCall { id, .. } | |
| | ThreadItem::CollabAgentToolCall { id, .. } | |
| | ThreadItem::SubAgentActivity { id, .. } | |
| | ThreadItem::ImageView { id, .. } | |
| | ThreadItem::EnteredReviewMode { id, .. } | |
| | ThreadItem::ExitedReviewMode { id, .. } | |
| | ThreadItem::ContextCompaction { id, .. } => id, | |
| ThreadItem::WebSearch(item) => &item.id, | |
| ThreadItem::Sleep(item) => &item.id, | |
| ThreadItem::ImageGeneration(item) => &item.id, | |
| } | |
| } | |
| } | |
| /// [UNSTABLE] Lifecycle state for an approval auto-review. | |
| pub enum GuardianApprovalReviewStatus { | |
| InProgress, | |
| Approved, | |
| Denied, | |
| TimedOut, | |
| Aborted, | |
| } | |
| /// [UNSTABLE] Source that produced a terminal approval auto-review decision. | |
| pub enum AutoReviewDecisionSource { | |
| Agent, | |
| } | |
| impl From<CoreGuardianAssessmentDecisionSource> for AutoReviewDecisionSource { | |
| fn from(value: CoreGuardianAssessmentDecisionSource) -> Self { | |
| match value { | |
| CoreGuardianAssessmentDecisionSource::Agent => Self::Agent, | |
| } | |
| } | |
| } | |
| /// [UNSTABLE] Risk level assigned by approval auto-review. | |
| pub enum GuardianRiskLevel { | |
| Low, | |
| Medium, | |
| High, | |
| Critical, | |
| } | |
| impl From<CoreGuardianRiskLevel> for GuardianRiskLevel { | |
| fn from(value: CoreGuardianRiskLevel) -> Self { | |
| match value { | |
| CoreGuardianRiskLevel::Low => Self::Low, | |
| CoreGuardianRiskLevel::Medium => Self::Medium, | |
| CoreGuardianRiskLevel::High => Self::High, | |
| CoreGuardianRiskLevel::Critical => Self::Critical, | |
| } | |
| } | |
| } | |
| /// [UNSTABLE] Authorization level assigned by approval auto-review. | |
| pub enum GuardianUserAuthorization { | |
| Unknown, | |
| Low, | |
| Medium, | |
| High, | |
| } | |
| impl From<CoreGuardianUserAuthorization> for GuardianUserAuthorization { | |
| fn from(value: CoreGuardianUserAuthorization) -> Self { | |
| match value { | |
| CoreGuardianUserAuthorization::Unknown => Self::Unknown, | |
| CoreGuardianUserAuthorization::Low => Self::Low, | |
| CoreGuardianUserAuthorization::Medium => Self::Medium, | |
| CoreGuardianUserAuthorization::High => Self::High, | |
| } | |
| } | |
| } | |
| /// [UNSTABLE] Temporary approval auto-review payload used by | |
| /// `item/autoApprovalReview/*` notifications. This shape is expected to change | |
| /// soon. | |
| pub struct GuardianApprovalReview { | |
| pub status: GuardianApprovalReviewStatus, | |
| pub risk_level: Option<GuardianRiskLevel>, | |
| pub user_authorization: Option<GuardianUserAuthorization>, | |
| pub rationale: Option<String>, | |
| } | |
| pub enum GuardianCommandSource { | |
| Shell, | |
| UnifiedExec, | |
| } | |
| impl From<CoreGuardianCommandSource> for GuardianCommandSource { | |
| fn from(value: CoreGuardianCommandSource) -> Self { | |
| match value { | |
| CoreGuardianCommandSource::Shell => Self::Shell, | |
| CoreGuardianCommandSource::UnifiedExec => Self::UnifiedExec, | |
| } | |
| } | |
| } | |
| impl From<GuardianCommandSource> for CoreGuardianCommandSource { | |
| fn from(value: GuardianCommandSource) -> Self { | |
| match value { | |
| GuardianCommandSource::Shell => Self::Shell, | |
| GuardianCommandSource::UnifiedExec => Self::UnifiedExec, | |
| } | |
| } | |
| } | |
| pub struct GuardianCommandReviewAction { | |
| pub source: GuardianCommandSource, | |
| pub command: String, | |
| pub cwd: LegacyAppPathString, | |
| } | |
| pub struct GuardianExecveReviewAction { | |
| pub source: GuardianCommandSource, | |
| pub program: String, | |
| pub argv: Vec<String>, | |
| pub cwd: AbsolutePathBuf, | |
| } | |
| pub struct GuardianApplyPatchReviewAction { | |
| pub cwd: LegacyAppPathString, | |
| pub files: Vec<LegacyAppPathString>, | |
| } | |
| pub struct GuardianNetworkAccessReviewAction { | |
| pub target: String, | |
| pub host: String, | |
| pub protocol: NetworkApprovalProtocol, | |
| pub port: u16, | |
| } | |
| pub struct GuardianMcpToolCallReviewAction { | |
| pub server: String, | |
| pub tool_name: String, | |
| pub connector_id: Option<String>, | |
| pub connector_name: Option<String>, | |
| pub tool_title: Option<String>, | |
| } | |
| pub struct GuardianRequestPermissionsReviewAction { | |
| pub reason: Option<String>, | |
| pub permissions: RequestPermissionProfile, | |
| } | |
| pub enum GuardianApprovalReviewAction { | |
| Command { | |
| source: GuardianCommandSource, | |
| command: String, | |
| cwd: LegacyAppPathString, | |
| }, | |
| Execve { | |
| source: GuardianCommandSource, | |
| program: String, | |
| argv: Vec<String>, | |
| cwd: AbsolutePathBuf, | |
| }, | |
| /// A child approval for input to an existing command execution item. | |
| WriteStdin { | |
| approval_id: String, | |
| process_id: String, | |
| stdin: String, | |
| cwd: LegacyAppPathString, | |
| }, | |
| ApplyPatch { | |
| cwd: LegacyAppPathString, | |
| files: Vec<LegacyAppPathString>, | |
| }, | |
| NetworkAccess { | |
| target: String, | |
| host: String, | |
| protocol: NetworkApprovalProtocol, | |
| port: u16, | |
| }, | |
| McpToolCall { | |
| server: String, | |
| tool_name: String, | |
| connector_id: Option<String>, | |
| connector_name: Option<String>, | |
| tool_title: Option<String>, | |
| }, | |
| RequestPermissions { | |
| reason: Option<String>, | |
| permissions: RequestPermissionProfile, | |
| }, | |
| } | |
| impl From<CoreGuardianAssessmentAction> for GuardianApprovalReviewAction { | |
| fn from(value: CoreGuardianAssessmentAction) -> Self { | |
| match value { | |
| CoreGuardianAssessmentAction::Command { | |
| source, | |
| command, | |
| cwd, | |
| } => Self::Command { | |
| source: source.into(), | |
| command, | |
| cwd, | |
| }, | |
| CoreGuardianAssessmentAction::Execve { | |
| source, | |
| program, | |
| argv, | |
| cwd, | |
| } => Self::Execve { | |
| source: source.into(), | |
| program, | |
| argv, | |
| cwd, | |
| }, | |
| CoreGuardianAssessmentAction::WriteStdin { | |
| approval_id, | |
| process_id, | |
| stdin, | |
| cwd, | |
| } => Self::WriteStdin { | |
| approval_id, | |
| process_id, | |
| stdin, | |
| cwd: cwd.into(), | |
| }, | |
| CoreGuardianAssessmentAction::ApplyPatch { cwd, files } => { | |
| Self::ApplyPatch { cwd, files } | |
| } | |
| CoreGuardianAssessmentAction::NetworkAccess { | |
| target, | |
| host, | |
| protocol, | |
| port, | |
| } => Self::NetworkAccess { | |
| target, | |
| host, | |
| protocol: protocol.into(), | |
| port, | |
| }, | |
| CoreGuardianAssessmentAction::McpToolCall { | |
| server, | |
| tool_name, | |
| connector_id, | |
| connector_name, | |
| tool_title, | |
| } => Self::McpToolCall { | |
| server, | |
| tool_name, | |
| connector_id, | |
| connector_name, | |
| tool_title, | |
| }, | |
| CoreGuardianAssessmentAction::RequestPermissions { | |
| reason, | |
| permissions, | |
| } => Self::RequestPermissions { | |
| reason, | |
| permissions: permissions.into(), | |
| }, | |
| } | |
| } | |
| } | |
| impl TryFrom<GuardianApprovalReviewAction> for CoreGuardianAssessmentAction { | |
| type Error = io::Error; | |
| fn try_from(value: GuardianApprovalReviewAction) -> Result<Self, Self::Error> { | |
| Ok(match value { | |
| GuardianApprovalReviewAction::Command { | |
| source, | |
| command, | |
| cwd, | |
| } => Self::Command { | |
| source: source.into(), | |
| command, | |
| cwd, | |
| }, | |
| GuardianApprovalReviewAction::Execve { | |
| source, | |
| program, | |
| argv, | |
| cwd, | |
| } => Self::Execve { | |
| source: source.into(), | |
| program, | |
| argv, | |
| cwd, | |
| }, | |
| GuardianApprovalReviewAction::WriteStdin { | |
| approval_id, | |
| process_id, | |
| stdin, | |
| cwd, | |
| } => Self::WriteStdin { | |
| approval_id, | |
| process_id, | |
| stdin, | |
| cwd: cwd | |
| .try_into() | |
| .map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err))?, | |
| }, | |
| GuardianApprovalReviewAction::ApplyPatch { cwd, files } => { | |
| Self::ApplyPatch { cwd, files } | |
| } | |
| GuardianApprovalReviewAction::NetworkAccess { | |
| target, | |
| host, | |
| protocol, | |
| port, | |
| } => Self::NetworkAccess { | |
| target, | |
| host, | |
| protocol: protocol.to_core(), | |
| port, | |
| }, | |
| GuardianApprovalReviewAction::McpToolCall { | |
| server, | |
| tool_name, | |
| connector_id, | |
| connector_name, | |
| tool_title, | |
| } => Self::McpToolCall { | |
| server, | |
| tool_name, | |
| connector_id, | |
| connector_name, | |
| tool_title, | |
| }, | |
| GuardianApprovalReviewAction::RequestPermissions { | |
| reason, | |
| permissions, | |
| } => Self::RequestPermissions { | |
| reason, | |
| permissions: permissions.try_into()?, | |
| }, | |
| }) | |
| } | |
| } | |
| pub(crate) fn web_search_action_from_core( | |
| value: codex_protocol::models::WebSearchAction, | |
| ) -> WebSearchAction { | |
| match value { | |
| codex_protocol::models::WebSearchAction::Search { query, queries } => { | |
| WebSearchAction::Search { query, queries } | |
| } | |
| codex_protocol::models::WebSearchAction::OpenPage { url } => { | |
| WebSearchAction::OpenPage { url } | |
| } | |
| codex_protocol::models::WebSearchAction::FindInPage { url, pattern } => { | |
| WebSearchAction::FindInPage { url, pattern } | |
| } | |
| codex_protocol::models::WebSearchAction::Other => WebSearchAction::Other, | |
| } | |
| } | |
| impl From<CoreTurnItem> for ThreadItem { | |
| fn from(value: CoreTurnItem) -> Self { | |
| match value { | |
| CoreTurnItem::UserMessage(user) => ThreadItem::UserMessage { | |
| id: user.id, | |
| client_id: user.client_id, | |
| content: user.content.into_iter().map(UserInput::from).collect(), | |
| }, | |
| CoreTurnItem::HookPrompt(hook_prompt) => ThreadItem::HookPrompt { | |
| id: hook_prompt.id, | |
| fragments: hook_prompt | |
| .fragments | |
| .into_iter() | |
| .map(HookPromptFragment::from) | |
| .collect(), | |
| }, | |
| CoreTurnItem::AgentMessage(agent) => { | |
| let text = agent | |
| .content | |
| .into_iter() | |
| .map(|entry| match entry { | |
| CoreAgentMessageContent::Text { text } => text, | |
| }) | |
| .collect::<String>(); | |
| ThreadItem::AgentMessage { | |
| id: agent.id, | |
| text, | |
| phase: agent.phase, | |
| memory_citation: agent.memory_citation.map(Into::into), | |
| delivery: agent.delivery, | |
| questions: agent.questions, | |
| } | |
| } | |
| CoreTurnItem::FunctionCallOutput(output) => ThreadItem::FunctionCallOutput { | |
| id: output.id, | |
| name: output.name, | |
| namespace: output.namespace, | |
| output: output.output, | |
| }, | |
| CoreTurnItem::Plan(plan) => ThreadItem::Plan { | |
| id: plan.id, | |
| text: plan.text, | |
| }, | |
| CoreTurnItem::Reasoning(reasoning) => ThreadItem::Reasoning { | |
| id: reasoning.id, | |
| summary: reasoning.summary_text, | |
| content: reasoning.raw_content, | |
| }, | |
| CoreTurnItem::CommandExecution(command) => { | |
| let presentation = CommandExecutionPresentation::from_raw( | |
| &command.command, | |
| &command.parsed_cmd, | |
| &command.cwd, | |
| ); | |
| ThreadItem::CommandExecution { | |
| id: command.id, | |
| model_context: command.model_context, | |
| plugin_id: command.plugin_id, | |
| script_path: command.script_path, | |
| command: presentation.command, | |
| cwd: command.cwd.clone().into(), | |
| process_id: command.process_id, | |
| source: command.source.into(), | |
| status: command.status.into(), | |
| command_actions: presentation.command_actions, | |
| aggregated_output: command | |
| .aggregated_output | |
| .filter(|output| !output.is_empty()), | |
| exit_code: command.exit_code, | |
| duration_ms: command | |
| .duration | |
| .and_then(|duration| i64::try_from(duration.as_millis()).ok()), | |
| } | |
| } | |
| CoreTurnItem::DynamicToolCall(call) => ThreadItem::DynamicToolCall { | |
| id: call.id, | |
| namespace: call.namespace, | |
| tool: call.tool, | |
| arguments: call.arguments, | |
| status: call.status.into(), | |
| content_items: call.content_items.map(|items| { | |
| items | |
| .into_iter() | |
| .map(DynamicToolCallOutputContentItem::from) | |
| .collect() | |
| }), | |
| success: call.success, | |
| duration_ms: call | |
| .duration | |
| .and_then(|duration| i64::try_from(duration.as_millis()).ok()), | |
| }, | |
| CoreTurnItem::CollabAgentToolCall(call) => ThreadItem::CollabAgentToolCall { | |
| id: call.id, | |
| tool: call.tool.into(), | |
| status: call.status.into(), | |
| sender_thread_id: call.sender_thread_id.to_string(), | |
| receiver_thread_ids: call | |
| .receiver_thread_ids | |
| .into_iter() | |
| .map(String::from) | |
| .collect(), | |
| prompt: call.prompt, | |
| model: call.model, | |
| reasoning_effort: call.reasoning_effort, | |
| agents_states: call | |
| .agents_states | |
| .into_iter() | |
| .map(|(thread_id, status)| (thread_id.to_string(), status.into())) | |
| .collect(), | |
| }, | |
| CoreTurnItem::SubAgentActivity(activity) => ThreadItem::SubAgentActivity { | |
| id: activity.id, | |
| kind: activity.kind.into(), | |
| agent_thread_id: activity.agent_thread_id.to_string(), | |
| agent_path: String::from(activity.agent_path), | |
| }, | |
| CoreTurnItem::WebSearch(search) => ThreadItem::WebSearch(WebSearchItem { | |
| id: search.id, | |
| query: search.query, | |
| action: Some(web_search_action_from_core(search.action)), | |
| results: search.results, | |
| }), | |
| CoreTurnItem::ImageView(image) => ThreadItem::ImageView { | |
| id: image.id, | |
| path: image.path.into(), | |
| }, | |
| CoreTurnItem::Extension(extension) => match extension { | |
| ExtensionItem::ImageGeneration(item) => ThreadItem::ImageGeneration(item), | |
| ExtensionItem::Sleep(item) => ThreadItem::Sleep(item), | |
| ExtensionItem::WebSearch(item) => ThreadItem::WebSearch(item), | |
| }, | |
| CoreTurnItem::ImageGeneration(image) => { | |
| ThreadItem::ImageGeneration(ImageGenerationItem { | |
| id: image.id, | |
| status: image.status, | |
| revised_prompt: image.revised_prompt, | |
| result: image.result, | |
| transparent_background: None, | |
| failure: None, | |
| saved_path: image.saved_path, | |
| imagegen_request_id: None, | |
| generation_id: None, | |
| }) | |
| } | |
| CoreTurnItem::EnteredReviewMode(review) => ThreadItem::EnteredReviewMode { | |
| id: review.id, | |
| review: review.user_facing_hint, | |
| }, | |
| CoreTurnItem::ExitedReviewMode(review) => ThreadItem::ExitedReviewMode { | |
| id: review.id, | |
| review: review_output_text(review.review_output.as_ref()), | |
| }, | |
| CoreTurnItem::FileChange(file_change) => ThreadItem::FileChange { | |
| id: file_change.id, | |
| changes: convert_patch_changes(&file_change.changes), | |
| status: file_change | |
| .status | |
| .as_ref() | |
| .map(PatchApplyStatus::from) | |
| .unwrap_or(PatchApplyStatus::InProgress), | |
| }, | |
| CoreTurnItem::McpToolCall(mcp) => { | |
| let duration_ms = mcp | |
| .duration | |
| .and_then(|duration| i64::try_from(duration.as_millis()).ok()); | |
| ThreadItem::McpToolCall { | |
| id: mcp.id, | |
| server: mcp.server, | |
| tool: mcp.tool, | |
| status: McpToolCallStatus::from(mcp.status), | |
| arguments: mcp.arguments, | |
| app_context: mcp.connector_id.map(|connector_id| McpToolCallAppContext { | |
| connector_id, | |
| link_id: mcp.link_id, | |
| resource_uri: mcp.mcp_app_resource_uri.clone(), | |
| app_name: mcp.app_name, | |
| action_name: mcp.action_name, | |
| }), | |
| mcp_app_resource_uri: mcp.mcp_app_resource_uri, | |
| mcp_app_ui: mcp.mcp_app_ui, | |
| plugin_id: mcp.plugin_id, | |
| read_only_hint: mcp.read_only_hint, | |
| result: mcp.result.map(McpToolCallResult::from).map(Box::new), | |
| error: mcp.error.map(McpToolCallError::from), | |
| duration_ms, | |
| } | |
| } | |
| CoreTurnItem::ContextCompaction(compaction) => { | |
| ThreadItem::ContextCompaction { id: compaction.id } | |
| } | |
| } | |
| } | |
| } | |
| impl From<codex_protocol::items::HookPromptFragment> for HookPromptFragment { | |
| fn from(value: codex_protocol::items::HookPromptFragment) -> Self { | |
| Self { | |
| text: value.text, | |
| hook_run_id: value.hook_run_id, | |
| } | |
| } | |
| } | |
| pub enum CommandExecutionStatus { | |
| InProgress, | |
| Completed, | |
| Failed, | |
| Declined, | |
| } | |
| impl From<CoreExecCommandStatus> for CommandExecutionStatus { | |
| fn from(value: CoreExecCommandStatus) -> Self { | |
| Self::from(&value) | |
| } | |
| } | |
| impl From<CoreCommandExecutionStatus> for CommandExecutionStatus { | |
| fn from(value: CoreCommandExecutionStatus) -> Self { | |
| match value { | |
| CoreCommandExecutionStatus::InProgress => Self::InProgress, | |
| CoreCommandExecutionStatus::Completed => Self::Completed, | |
| CoreCommandExecutionStatus::Failed => Self::Failed, | |
| CoreCommandExecutionStatus::Declined => Self::Declined, | |
| } | |
| } | |
| } | |
| impl From<&CoreExecCommandStatus> for CommandExecutionStatus { | |
| fn from(value: &CoreExecCommandStatus) -> Self { | |
| match value { | |
| CoreExecCommandStatus::Completed => CommandExecutionStatus::Completed, | |
| CoreExecCommandStatus::Failed => CommandExecutionStatus::Failed, | |
| CoreExecCommandStatus::Declined => CommandExecutionStatus::Declined, | |
| } | |
| } | |
| } | |
| v2_enum_from_core! { | |
| pub enum CommandExecutionSource from CoreExecCommandSource { | |
| Agent, | |
| UserShell, | |
| UnifiedExecStartup, | |
| UnifiedExecInteraction, | |
| } | |
| } | |
| pub enum CollabAgentTool { | |
| SpawnAgent, | |
| SendInput, | |
| ResumeAgent, | |
| Wait, | |
| CloseAgent, | |
| SendMessage, | |
| FollowupTask, | |
| InterruptAgent, | |
| ListAgents, | |
| } | |
| pub struct FileUpdateChange { | |
| pub path: String, | |
| pub kind: PatchChangeKind, | |
| pub diff: String, | |
| } | |
| pub enum PatchChangeKind { | |
| Add, | |
| Delete, | |
| Update { move_path: Option<PathBuf> }, | |
| } | |
| pub enum PatchApplyStatus { | |
| InProgress, | |
| Completed, | |
| Failed, | |
| Declined, | |
| } | |
| impl From<CorePatchApplyStatus> for PatchApplyStatus { | |
| fn from(value: CorePatchApplyStatus) -> Self { | |
| Self::from(&value) | |
| } | |
| } | |
| impl From<&CorePatchApplyStatus> for PatchApplyStatus { | |
| fn from(value: &CorePatchApplyStatus) -> Self { | |
| match value { | |
| CorePatchApplyStatus::Completed => PatchApplyStatus::Completed, | |
| CorePatchApplyStatus::Failed => PatchApplyStatus::Failed, | |
| CorePatchApplyStatus::Declined => PatchApplyStatus::Declined, | |
| } | |
| } | |
| } | |
| impl From<CoreMcpToolCallStatus> for McpToolCallStatus { | |
| fn from(value: CoreMcpToolCallStatus) -> Self { | |
| match value { | |
| CoreMcpToolCallStatus::InProgress => McpToolCallStatus::InProgress, | |
| CoreMcpToolCallStatus::Completed => McpToolCallStatus::Completed, | |
| CoreMcpToolCallStatus::Failed => McpToolCallStatus::Failed, | |
| } | |
| } | |
| } | |
| impl From<CoreDynamicToolCallStatus> for DynamicToolCallStatus { | |
| fn from(value: CoreDynamicToolCallStatus) -> Self { | |
| match value { | |
| CoreDynamicToolCallStatus::InProgress => Self::InProgress, | |
| CoreDynamicToolCallStatus::Completed => Self::Completed, | |
| CoreDynamicToolCallStatus::Failed => Self::Failed, | |
| } | |
| } | |
| } | |
| pub enum McpToolCallStatus { | |
| InProgress, | |
| Completed, | |
| Failed, | |
| } | |
| pub enum DynamicToolCallStatus { | |
| InProgress, | |
| Completed, | |
| Failed, | |
| } | |
| pub enum CollabAgentToolCallStatus { | |
| InProgress, | |
| Completed, | |
| Failed, | |
| Interrupted, | |
| } | |
| impl From<CoreCollabAgentTool> for CollabAgentTool { | |
| fn from(value: CoreCollabAgentTool) -> Self { | |
| match value { | |
| CoreCollabAgentTool::SpawnAgent => Self::SpawnAgent, | |
| CoreCollabAgentTool::SendInput => Self::SendInput, | |
| CoreCollabAgentTool::ResumeAgent => Self::ResumeAgent, | |
| CoreCollabAgentTool::Wait => Self::Wait, | |
| CoreCollabAgentTool::CloseAgent => Self::CloseAgent, | |
| CoreCollabAgentTool::SendMessage => Self::SendMessage, | |
| CoreCollabAgentTool::FollowupTask => Self::FollowupTask, | |
| CoreCollabAgentTool::InterruptAgent => Self::InterruptAgent, | |
| CoreCollabAgentTool::ListAgents => Self::ListAgents, | |
| } | |
| } | |
| } | |
| impl From<CoreCollabAgentToolCallStatus> for CollabAgentToolCallStatus { | |
| fn from(value: CoreCollabAgentToolCallStatus) -> Self { | |
| match value { | |
| CoreCollabAgentToolCallStatus::InProgress => Self::InProgress, | |
| CoreCollabAgentToolCallStatus::Completed => Self::Completed, | |
| CoreCollabAgentToolCallStatus::Failed => Self::Failed, | |
| CoreCollabAgentToolCallStatus::Interrupted => Self::Interrupted, | |
| } | |
| } | |
| } | |
| pub enum SubAgentActivityKind { | |
| Started, | |
| Interacted, | |
| Interrupted, | |
| Completed, | |
| } | |
| impl From<CoreSubAgentActivityKind> for SubAgentActivityKind { | |
| fn from(value: CoreSubAgentActivityKind) -> Self { | |
| match value { | |
| CoreSubAgentActivityKind::Started => SubAgentActivityKind::Started, | |
| CoreSubAgentActivityKind::Interacted => SubAgentActivityKind::Interacted, | |
| CoreSubAgentActivityKind::Interrupted => SubAgentActivityKind::Interrupted, | |
| CoreSubAgentActivityKind::Completed => SubAgentActivityKind::Completed, | |
| } | |
| } | |
| } | |
| pub enum CollabAgentStatus { | |
| PendingInit, | |
| Running, | |
| Interrupted, | |
| Completed, | |
| Errored, | |
| Shutdown, | |
| NotFound, | |
| } | |
| pub struct CollabAgentState { | |
| pub status: CollabAgentStatus, | |
| pub message: Option<String>, | |
| } | |
| impl From<CoreAgentStatus> for CollabAgentState { | |
| fn from(value: CoreAgentStatus) -> Self { | |
| match value { | |
| CoreAgentStatus::PendingInit => Self { | |
| status: CollabAgentStatus::PendingInit, | |
| message: None, | |
| }, | |
| CoreAgentStatus::Running => Self { | |
| status: CollabAgentStatus::Running, | |
| message: None, | |
| }, | |
| CoreAgentStatus::Interrupted => Self { | |
| status: CollabAgentStatus::Interrupted, | |
| message: None, | |
| }, | |
| CoreAgentStatus::Completed(message) => Self { | |
| status: CollabAgentStatus::Completed, | |
| message, | |
| }, | |
| CoreAgentStatus::Errored(message) => Self { | |
| status: CollabAgentStatus::Errored, | |
| message: Some(message), | |
| }, | |
| CoreAgentStatus::Shutdown => Self { | |
| status: CollabAgentStatus::Shutdown, | |
| message: None, | |
| }, | |
| CoreAgentStatus::NotFound => Self { | |
| status: CollabAgentStatus::NotFound, | |
| message: None, | |
| }, | |
| } | |
| } | |
| } | |
| pub struct ItemStartedNotification { | |
| pub item: ThreadItem, | |
| pub thread_id: String, | |
| pub turn_id: String, | |
| /// Unix timestamp (in milliseconds) when this item lifecycle started. | |
| pub started_at_ms: i64, | |
| } | |
| /// [UNSTABLE] Temporary notification payload for approval auto-review. This | |
| /// shape is expected to change soon. | |
| pub struct ItemGuardianApprovalReviewStartedNotification { | |
| pub thread_id: String, | |
| pub turn_id: String, | |
| /// Unix timestamp (in milliseconds) when this review started. | |
| pub started_at_ms: i64, | |
| /// Stable identifier for this review. | |
| pub review_id: String, | |
| /// Identifier for the reviewed item or tool call when one exists. | |
| /// | |
| /// In most cases, one review maps to one target item. The exceptions are | |
| /// - execve reviews, where a single command may contain multiple execve | |
| /// calls to review (only possible when using the shell_zsh_fork feature) | |
| /// - stdin reviews, which refer to the existing parent command item and | |
| /// have a separate approval ID in the action payload | |
| /// - network policy reviews, where there is no target item | |
| /// | |
| /// A network call is triggered by a CommandExecution item, so having a | |
| /// target_item_id set to the CommandExecution item would be misleading | |
| /// because the review is about the network call, not the command execution. | |
| /// Therefore, target_item_id is set to None for network policy reviews. | |
| pub target_item_id: Option<String>, | |
| pub review: GuardianApprovalReview, | |
| pub action: GuardianApprovalReviewAction, | |
| } | |
| /// [UNSTABLE] Temporary notification payload for approval auto-review. This | |
| /// shape is expected to change soon. | |
| pub struct ItemGuardianApprovalReviewCompletedNotification { | |
| pub thread_id: String, | |
| pub turn_id: String, | |
| /// Unix timestamp (in milliseconds) when this review started. | |
| pub started_at_ms: i64, | |
| /// Unix timestamp (in milliseconds) when this review completed. | |
| pub completed_at_ms: i64, | |
| /// Stable identifier for this review. | |
| pub review_id: String, | |
| /// Identifier for the reviewed item or tool call when one exists. | |
| /// | |
| /// In most cases, one review maps to one target item. The exceptions are | |
| /// - execve reviews, where a single command may contain multiple execve | |
| /// calls to review (only possible when using the shell_zsh_fork feature) | |
| /// - stdin reviews, which refer to the existing parent command item and | |
| /// have a separate approval ID in the action payload | |
| /// - network policy reviews, where there is no target item | |
| /// | |
| /// A network call is triggered by a CommandExecution item, so having a | |
| /// target_item_id set to the CommandExecution item would be misleading | |
| /// because the review is about the network call, not the command execution. | |
| /// Therefore, target_item_id is set to None for network policy reviews. | |
| pub target_item_id: Option<String>, | |
| pub decision_source: AutoReviewDecisionSource, | |
| pub review: GuardianApprovalReview, | |
| pub action: GuardianApprovalReviewAction, | |
| } | |
| pub struct ItemCompletedNotification { | |
| pub item: ThreadItem, | |
| pub thread_id: String, | |
| pub turn_id: String, | |
| /// Unix timestamp (in milliseconds) when this item lifecycle completed. | |
| pub completed_at_ms: i64, | |
| } | |
| pub struct RawResponseItemCompletedNotification { | |
| pub thread_id: String, | |
| pub turn_id: String, | |
| pub item: ResponseItem, | |
| } | |
| // Item-specific progress notifications | |
| pub struct AgentMessageDeltaNotification { | |
| pub thread_id: String, | |
| pub turn_id: String, | |
| pub item_id: String, | |
| pub delta: String, | |
| } | |
| /// EXPERIMENTAL - proposed plan streaming deltas for plan items. Clients should | |
| /// not assume concatenated deltas match the completed plan item content. | |
| pub struct PlanDeltaNotification { | |
| pub thread_id: String, | |
| pub turn_id: String, | |
| pub item_id: String, | |
| pub delta: String, | |
| } | |
| pub struct ReasoningSummaryTextDeltaNotification { | |
| pub thread_id: String, | |
| pub turn_id: String, | |
| pub item_id: String, | |
| pub delta: String, | |
| pub summary_index: i64, | |
| } | |
| pub struct ReasoningSummaryPartAddedNotification { | |
| pub thread_id: String, | |
| pub turn_id: String, | |
| pub item_id: String, | |
| pub summary_index: i64, | |
| } | |
| pub struct ReasoningTextDeltaNotification { | |
| pub thread_id: String, | |
| pub turn_id: String, | |
| pub item_id: String, | |
| pub delta: String, | |
| pub content_index: i64, | |
| } | |
| pub struct TerminalInteractionNotification { | |
| pub thread_id: String, | |
| pub turn_id: String, | |
| pub item_id: String, | |
| pub process_id: String, | |
| pub stdin: String, | |
| } | |
| pub struct CommandExecutionOutputDeltaNotification { | |
| pub thread_id: String, | |
| pub turn_id: String, | |
| pub item_id: String, | |
| pub delta: String, | |
| } | |
| /// Deprecated legacy notification for `apply_patch` textual output. | |
| /// | |
| /// The server no longer emits this notification. | |
| pub struct FileChangeOutputDeltaNotification { | |
| pub thread_id: String, | |
| pub turn_id: String, | |
| pub item_id: String, | |
| pub delta: String, | |
| } | |
| pub struct FileChangePatchUpdatedNotification { | |
| pub thread_id: String, | |
| pub turn_id: String, | |
| pub item_id: String, | |
| pub changes: Vec<FileUpdateChange>, | |
| } | |
| v2_enum_from_core! { | |
| /// Distinguishes a command approval from input sent to an existing terminal. | |
| pub enum CommandExecutionApprovalKind from CoreExecApprovalKind { | |
| Command, | |
| WriteStdin, | |
| } | |
| } | |
| pub struct CommandExecutionRequestApprovalParams { | |
| /// Kind of action under review. Defaults to `command` for older servers. | |
| pub kind: CommandExecutionApprovalKind, | |
| pub thread_id: String, | |
| pub turn_id: String, | |
| pub item_id: String, | |
| /// Unix timestamp (in milliseconds) when this approval request started. | |
| pub started_at_ms: i64, | |
| /// Unique identifier for this specific approval callback. | |
| /// | |
| /// For regular shell/unified_exec approvals, this is null. | |
| /// | |
| /// For zsh-exec-bridge subcommand approvals, multiple callbacks can belong to | |
| /// one parent `itemId`, so `approvalId` is a distinct opaque callback id | |
| /// (a UUID) used to disambiguate routing. | |
| /// Stdin approvals also use a distinct callback id; inspect `kind` to distinguish them. | |
| pub approval_id: Option<String>, | |
| /// Environment in which the command will run. | |
| pub environment_id: Option<String>, | |
| /// Optional explanatory reason (e.g. request for network access). | |
| pub reason: Option<String>, | |
| /// Optional context for a managed-network approval prompt. | |
| pub network_approval_context: Option<NetworkApprovalContext>, | |
| /// The command to be executed. | |
| pub command: Option<String>, | |
| /// The command's working directory. | |
| pub cwd: Option<LegacyAppPathString>, | |
| /// Best-effort parsed command actions for friendly display. | |
| pub command_actions: Option<Vec<CommandAction>>, | |
| /// Optional additional permissions requested for this command. | |
| pub additional_permissions: Option<AdditionalPermissionProfile>, | |
| /// Optional proposed execpolicy amendment to allow similar commands without prompting. | |
| pub proposed_execpolicy_amendment: Option<ExecPolicyAmendment>, | |
| /// Optional proposed network policy amendments (allow/deny host) for future requests. | |
| pub proposed_network_policy_amendments: Option<Vec<NetworkPolicyAmendment>>, | |
| /// Ordered list of decisions the client may present for this prompt. | |
| pub available_decisions: Option<Vec<CommandExecutionApprovalDecision>>, | |
| } | |
| impl CommandExecutionRequestApprovalParams { | |
| pub fn strip_experimental_fields(&mut self) { | |
| // TODO: Avoid hardcoding individual experimental fields here. | |
| // We need a generic outbound compatibility design for stripping or | |
| // otherwise handling experimental server->client payloads. | |
| self.additional_permissions = None; | |
| } | |
| } | |
| pub struct CommandExecutionRequestApprovalResponse { | |
| pub decision: CommandExecutionApprovalDecision, | |
| } | |
| pub struct FileChangeRequestApprovalParams { | |
| pub thread_id: String, | |
| pub turn_id: String, | |
| pub item_id: String, | |
| /// Unix timestamp (in milliseconds) when this approval request started. | |
| pub started_at_ms: i64, | |
| /// Optional explanatory reason (e.g. request for extra write access). | |
| pub reason: Option<String>, | |
| /// [UNSTABLE] When set, the agent is asking the user to allow writes under this root | |
| /// for the remainder of the session (unclear if this is honored today). | |
| pub grant_root: Option<PathBuf>, | |
| } | |
| pub struct FileChangeRequestApprovalResponse { | |
| pub decision: FileChangeApprovalDecision, | |
| } | |
| pub struct DynamicToolCallParams { | |
| pub thread_id: String, | |
| pub turn_id: String, | |
| pub call_id: String, | |
| pub namespace: Option<String>, | |
| pub tool: String, | |
| pub arguments: JsonValue, | |
| } | |
| pub struct DynamicToolCallResponse { | |
| pub content_items: Vec<DynamicToolCallOutputContentItem>, | |
| pub success: bool, | |
| } | |
| pub enum DynamicToolCallOutputContentItem { | |
| InputText { text: String }, | |
| InputImage { image_url: String }, | |
| InputAudio { audio_url: String }, | |
| } | |
| impl From<codex_protocol::dynamic_tools::DynamicToolCallOutputContentItem> | |
| for DynamicToolCallOutputContentItem | |
| { | |
| fn from(item: codex_protocol::dynamic_tools::DynamicToolCallOutputContentItem) -> Self { | |
| match item { | |
| codex_protocol::dynamic_tools::DynamicToolCallOutputContentItem::InputText { text } => { | |
| Self::InputText { text } | |
| } | |
| codex_protocol::dynamic_tools::DynamicToolCallOutputContentItem::InputImage { | |
| image_url, | |
| } => Self::InputImage { image_url }, | |
| codex_protocol::dynamic_tools::DynamicToolCallOutputContentItem::InputAudio { | |
| audio_url, | |
| } => Self::InputAudio { audio_url }, | |
| } | |
| } | |
| } | |
| impl From<DynamicToolCallOutputContentItem> | |
| for codex_protocol::dynamic_tools::DynamicToolCallOutputContentItem | |
| { | |
| fn from(item: DynamicToolCallOutputContentItem) -> Self { | |
| match item { | |
| DynamicToolCallOutputContentItem::InputText { text } => Self::InputText { text }, | |
| DynamicToolCallOutputContentItem::InputImage { image_url } => { | |
| Self::InputImage { image_url } | |
| } | |
| DynamicToolCallOutputContentItem::InputAudio { audio_url } => { | |
| Self::InputAudio { audio_url } | |
| } | |
| } | |
| } | |
| } | |
| /// EXPERIMENTAL. Defines a single selectable option for request_user_input. | |
| pub struct ToolRequestUserInputOption { | |
| pub label: String, | |
| pub description: String, | |
| } | |
| /// EXPERIMENTAL. Represents one request_user_input question and its required options. | |
| pub struct ToolRequestUserInputQuestion { | |
| pub id: String, | |
| pub header: String, | |
| pub question: String, | |
| pub is_other: bool, | |
| pub is_secret: bool, | |
| pub options: Option<Vec<ToolRequestUserInputOption>>, | |
| } | |
| /// EXPERIMENTAL. Params sent with a request_user_input event. | |
| pub struct ToolRequestUserInputParams { | |
| pub thread_id: String, | |
| pub turn_id: String, | |
| pub item_id: String, | |
| pub questions: Vec<ToolRequestUserInputQuestion>, | |
| pub is_blocking: bool, | |
| /// @deprecated Use `isBlocking` to decide whether the request should block. | |
| pub auto_resolution_ms: Option<u64>, | |
| } | |
| impl<'de> Deserialize<'de> for ToolRequestUserInputParams { | |
| fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | |
| where | |
| D: serde::Deserializer<'de>, | |
| { | |
| struct WireToolRequestUserInputParams { | |
| thread_id: String, | |
| turn_id: String, | |
| item_id: String, | |
| questions: Vec<ToolRequestUserInputQuestion>, | |
| is_blocking: Option<bool>, | |
| auto_resolution_ms: Option<u64>, | |
| } | |
| let wire = WireToolRequestUserInputParams::deserialize(deserializer)?; | |
| Ok(Self { | |
| thread_id: wire.thread_id, | |
| turn_id: wire.turn_id, | |
| item_id: wire.item_id, | |
| questions: wire.questions, | |
| is_blocking: wire.is_blocking.unwrap_or(true), | |
| auto_resolution_ms: wire.auto_resolution_ms, | |
| }) | |
| } | |
| } | |
| /// EXPERIMENTAL. Captures a user's answer to a request_user_input question. | |
| pub struct ToolRequestUserInputAnswer { | |
| pub answers: Vec<String>, | |
| } | |
| /// EXPERIMENTAL. Response payload mapping question ids to answers. | |
| pub struct ToolRequestUserInputResponse { | |
| pub answers: HashMap<String, ToolRequestUserInputAnswer>, | |
| } | |