diff --git a/codex-rs/exec/src/cli.rs b/codex-rs/exec/src/cli.rs index 0df114cb..57217b1f 100644 --- a/codex-rs/exec/src/cli.rs +++ b/codex-rs/exec/src/cli.rs @@ -64,20 +64,9 @@ pub struct Cli { pub color: Color, /// Print events to stdout as JSONL. - #[arg( - long = "json", - default_value_t = false, - conflicts_with = "experimental_json" - )] + #[arg(long = "json", alias = "experimental-json", default_value_t = false)] pub json: bool, - #[arg( - long = "experimental-json", - default_value_t = false, - conflicts_with = "json" - )] - pub experimental_json: bool, - /// Whether to include the plan tool in the conversation. #[arg(long = "include-plan-tool", default_value_t = false)] pub include_plan_tool: bool, diff --git a/codex-rs/exec/src/event_processor_with_json_output.rs b/codex-rs/exec/src/event_processor_with_json_output.rs deleted file mode 100644 index c9d1127f..00000000 --- a/codex-rs/exec/src/event_processor_with_json_output.rs +++ /dev/null @@ -1,64 +0,0 @@ -use std::collections::HashMap; -use std::path::PathBuf; - -use codex_core::config::Config; -use codex_core::protocol::Event; -use codex_core::protocol::EventMsg; -use codex_core::protocol::SessionConfiguredEvent; -use codex_core::protocol::TaskCompleteEvent; -use serde_json::json; - -use crate::event_processor::CodexStatus; -use crate::event_processor::EventProcessor; -use crate::event_processor::handle_last_message; -use codex_common::create_config_summary_entries; - -pub(crate) struct EventProcessorWithJsonOutput { - last_message_path: Option, -} - -impl EventProcessorWithJsonOutput { - pub fn new(last_message_path: Option) -> Self { - Self { last_message_path } - } -} - -impl EventProcessor for EventProcessorWithJsonOutput { - fn print_config_summary(&mut self, config: &Config, prompt: &str, _: &SessionConfiguredEvent) { - let entries = create_config_summary_entries(config) - .into_iter() - .map(|(key, value)| (key.to_string(), value)) - .collect::>(); - #[expect(clippy::expect_used)] - let config_json = - serde_json::to_string(&entries).expect("Failed to serialize config summary to JSON"); - println!("{config_json}"); - - let prompt_json = json!({ - "prompt": prompt, - }); - println!("{prompt_json}"); - } - - fn process_event(&mut self, event: Event) -> CodexStatus { - match event.msg { - EventMsg::AgentMessageDelta(_) | EventMsg::AgentReasoningDelta(_) => { - // Suppress streaming events in JSON mode. - CodexStatus::Running - } - EventMsg::TaskComplete(TaskCompleteEvent { last_agent_message }) => { - if let Some(output_file) = self.last_message_path.as_deref() { - handle_last_message(last_agent_message.as_deref(), output_file); - } - CodexStatus::InitiateShutdown - } - EventMsg::ShutdownComplete => CodexStatus::Shutdown, - _ => { - if let Ok(line) = serde_json::to_string(&event) { - println!("{line}"); - } - CodexStatus::Running - } - } - } -} diff --git a/codex-rs/exec/src/experimental_event_processor_with_json_output.rs b/codex-rs/exec/src/event_processor_with_jsonl_output.rs similarity index 98% rename from codex-rs/exec/src/experimental_event_processor_with_json_output.rs rename to codex-rs/exec/src/event_processor_with_jsonl_output.rs index 01c439ed..b3c82fc9 100644 --- a/codex-rs/exec/src/experimental_event_processor_with_json_output.rs +++ b/codex-rs/exec/src/event_processor_with_jsonl_output.rs @@ -51,7 +51,7 @@ use codex_core::protocol::WebSearchEndEvent; use tracing::error; use tracing::warn; -pub struct ExperimentalEventProcessorWithJsonOutput { +pub struct EventProcessorWithJsonOutput { last_message_path: Option, next_event_id: AtomicU64, // Tracks running commands by call_id, including the associated item id. @@ -83,7 +83,7 @@ struct RunningMcpToolCall { item_id: String, } -impl ExperimentalEventProcessorWithJsonOutput { +impl EventProcessorWithJsonOutput { pub fn new(last_message_path: Option) -> Self { Self { last_message_path, @@ -420,7 +420,7 @@ impl ExperimentalEventProcessorWithJsonOutput { } } -impl EventProcessor for ExperimentalEventProcessorWithJsonOutput { +impl EventProcessor for EventProcessorWithJsonOutput { fn print_config_summary(&mut self, _: &Config, _: &str, ev: &SessionConfiguredEvent) { self.process_event(Event { id: "".to_string(), diff --git a/codex-rs/exec/src/lib.rs b/codex-rs/exec/src/lib.rs index bdf03650..d77f9685 100644 --- a/codex-rs/exec/src/lib.rs +++ b/codex-rs/exec/src/lib.rs @@ -1,9 +1,8 @@ mod cli; mod event_processor; mod event_processor_with_human_output; -pub mod event_processor_with_json_output; +pub mod event_processor_with_jsonl_output; pub mod exec_events; -pub mod experimental_event_processor_with_json_output; pub use cli::Cli; use codex_core::AuthManager; @@ -22,8 +21,7 @@ use codex_core::protocol::TaskCompleteEvent; use codex_ollama::DEFAULT_OSS_MODEL; use codex_protocol::config_types::SandboxMode; use event_processor_with_human_output::EventProcessorWithHumanOutput; -use event_processor_with_json_output::EventProcessorWithJsonOutput; -use experimental_event_processor_with_json_output::ExperimentalEventProcessorWithJsonOutput; +use event_processor_with_jsonl_output::EventProcessorWithJsonOutput; use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge; use serde_json::Value; use std::io::IsTerminal; @@ -59,7 +57,6 @@ pub async fn run_main(cli: Cli, codex_linux_sandbox_exe: Option) -> any color, last_message_file, json: json_mode, - experimental_json, sandbox_mode: sandbox_mode_cli_arg, prompt, output_schema: output_schema_path, @@ -212,17 +209,8 @@ pub async fn run_main(cli: Cli, codex_linux_sandbox_exe: Option) -> any let _ = tracing_subscriber::registry().with(fmt_layer).try_init(); } - let mut event_processor: Box = match (json_mode, experimental_json) { - (_, true) => Box::new(ExperimentalEventProcessorWithJsonOutput::new( - last_message_file.clone(), - )), - (true, _) => { - eprintln!( - "The existing `--json` output format is being deprecated. Please try the new format using `--experimental-json`." - ); - - Box::new(EventProcessorWithJsonOutput::new(last_message_file.clone())) - } + let mut event_processor: Box = match json_mode { + true => Box::new(EventProcessorWithJsonOutput::new(last_message_file.clone())), _ => Box::new(EventProcessorWithHumanOutput::create_with_ansi( stdout_with_ansi, &config, diff --git a/codex-rs/exec/tests/event_processor_with_json_output.rs b/codex-rs/exec/tests/event_processor_with_json_output.rs index 8ab5f3b2..8489250b 100644 --- a/codex-rs/exec/tests/event_processor_with_json_output.rs +++ b/codex-rs/exec/tests/event_processor_with_json_output.rs @@ -13,6 +13,7 @@ use codex_core::protocol::PatchApplyBeginEvent; use codex_core::protocol::PatchApplyEndEvent; use codex_core::protocol::SessionConfiguredEvent; use codex_core::protocol::WebSearchEndEvent; +use codex_exec::event_processor_with_jsonl_output::EventProcessorWithJsonOutput; use codex_exec::exec_events::AssistantMessageItem; use codex_exec::exec_events::CommandExecutionItem; use codex_exec::exec_events::CommandExecutionStatus; @@ -36,7 +37,6 @@ use codex_exec::exec_events::TurnFailedEvent; use codex_exec::exec_events::TurnStartedEvent; use codex_exec::exec_events::Usage; use codex_exec::exec_events::WebSearchItem; -use codex_exec::experimental_event_processor_with_json_output::ExperimentalEventProcessorWithJsonOutput; use mcp_types::CallToolResult; use pretty_assertions::assert_eq; use std::path::PathBuf; @@ -51,7 +51,7 @@ fn event(id: &str, msg: EventMsg) -> Event { #[test] fn session_configured_produces_thread_started_event() { - let mut ep = ExperimentalEventProcessorWithJsonOutput::new(None); + let mut ep = EventProcessorWithJsonOutput::new(None); let session_id = codex_protocol::mcp_protocol::ConversationId::from_string( "67e55044-10b1-426f-9247-bb680e5fe0c8", ) @@ -80,7 +80,7 @@ fn session_configured_produces_thread_started_event() { #[test] fn task_started_produces_turn_started_event() { - let mut ep = ExperimentalEventProcessorWithJsonOutput::new(None); + let mut ep = EventProcessorWithJsonOutput::new(None); let out = ep.collect_thread_events(&event( "t1", EventMsg::TaskStarted(codex_core::protocol::TaskStartedEvent { @@ -93,7 +93,7 @@ fn task_started_produces_turn_started_event() { #[test] fn web_search_end_emits_item_completed() { - let mut ep = ExperimentalEventProcessorWithJsonOutput::new(None); + let mut ep = EventProcessorWithJsonOutput::new(None); let query = "rust async await".to_string(); let out = ep.collect_thread_events(&event( "w1", @@ -120,7 +120,7 @@ fn plan_update_emits_todo_list_started_updated_and_completed() { use codex_core::plan_tool::StepStatus; use codex_core::plan_tool::UpdatePlanArgs; - let mut ep = ExperimentalEventProcessorWithJsonOutput::new(None); + let mut ep = EventProcessorWithJsonOutput::new(None); // First plan update => item.started (todo_list) let first = event( @@ -237,7 +237,7 @@ fn plan_update_emits_todo_list_started_updated_and_completed() { #[test] fn mcp_tool_call_begin_and_end_emit_item_events() { - let mut ep = ExperimentalEventProcessorWithJsonOutput::new(None); + let mut ep = EventProcessorWithJsonOutput::new(None); let invocation = McpInvocation { server: "server_a".to_string(), tool: "tool_x".to_string(), @@ -297,7 +297,7 @@ fn mcp_tool_call_begin_and_end_emit_item_events() { #[test] fn mcp_tool_call_failure_sets_failed_status() { - let mut ep = ExperimentalEventProcessorWithJsonOutput::new(None); + let mut ep = EventProcessorWithJsonOutput::new(None); let invocation = McpInvocation { server: "server_b".to_string(), tool: "tool_y".to_string(), @@ -344,7 +344,7 @@ fn plan_update_after_complete_starts_new_todo_list_with_new_id() { use codex_core::plan_tool::StepStatus; use codex_core::plan_tool::UpdatePlanArgs; - let mut ep = ExperimentalEventProcessorWithJsonOutput::new(None); + let mut ep = EventProcessorWithJsonOutput::new(None); // First turn: start + complete let start = event( @@ -389,7 +389,7 @@ fn plan_update_after_complete_starts_new_todo_list_with_new_id() { #[test] fn agent_reasoning_produces_item_completed_reasoning() { - let mut ep = ExperimentalEventProcessorWithJsonOutput::new(None); + let mut ep = EventProcessorWithJsonOutput::new(None); let ev = event( "e1", EventMsg::AgentReasoning(AgentReasoningEvent { @@ -412,7 +412,7 @@ fn agent_reasoning_produces_item_completed_reasoning() { #[test] fn agent_message_produces_item_completed_assistant_message() { - let mut ep = ExperimentalEventProcessorWithJsonOutput::new(None); + let mut ep = EventProcessorWithJsonOutput::new(None); let ev = event( "e1", EventMsg::AgentMessage(AgentMessageEvent { @@ -435,7 +435,7 @@ fn agent_message_produces_item_completed_assistant_message() { #[test] fn error_event_produces_error() { - let mut ep = ExperimentalEventProcessorWithJsonOutput::new(None); + let mut ep = EventProcessorWithJsonOutput::new(None); let out = ep.collect_thread_events(&event( "e1", EventMsg::Error(codex_core::protocol::ErrorEvent { @@ -452,7 +452,7 @@ fn error_event_produces_error() { #[test] fn stream_error_event_produces_error() { - let mut ep = ExperimentalEventProcessorWithJsonOutput::new(None); + let mut ep = EventProcessorWithJsonOutput::new(None); let out = ep.collect_thread_events(&event( "e1", EventMsg::StreamError(codex_core::protocol::StreamErrorEvent { @@ -469,7 +469,7 @@ fn stream_error_event_produces_error() { #[test] fn error_followed_by_task_complete_produces_turn_failed() { - let mut ep = ExperimentalEventProcessorWithJsonOutput::new(None); + let mut ep = EventProcessorWithJsonOutput::new(None); let error_event = event( "e1", @@ -502,7 +502,7 @@ fn error_followed_by_task_complete_produces_turn_failed() { #[test] fn exec_command_end_success_produces_completed_command_item() { - let mut ep = ExperimentalEventProcessorWithJsonOutput::new(None); + let mut ep = EventProcessorWithJsonOutput::new(None); // Begin -> no output let begin = event( @@ -562,7 +562,7 @@ fn exec_command_end_success_produces_completed_command_item() { #[test] fn exec_command_end_failure_produces_failed_command_item() { - let mut ep = ExperimentalEventProcessorWithJsonOutput::new(None); + let mut ep = EventProcessorWithJsonOutput::new(None); // Begin -> no output let begin = event( @@ -621,7 +621,7 @@ fn exec_command_end_failure_produces_failed_command_item() { #[test] fn exec_command_end_without_begin_is_ignored() { - let mut ep = ExperimentalEventProcessorWithJsonOutput::new(None); + let mut ep = EventProcessorWithJsonOutput::new(None); // End event arrives without a prior Begin; should produce no thread events. let end_only = event( @@ -642,7 +642,7 @@ fn exec_command_end_without_begin_is_ignored() { #[test] fn patch_apply_success_produces_item_completed_patchapply() { - let mut ep = ExperimentalEventProcessorWithJsonOutput::new(None); + let mut ep = EventProcessorWithJsonOutput::new(None); // Prepare a patch with multiple kinds of changes let mut changes = std::collections::HashMap::new(); @@ -724,7 +724,7 @@ fn patch_apply_success_produces_item_completed_patchapply() { #[test] fn patch_apply_failure_produces_item_completed_patchapply_failed() { - let mut ep = ExperimentalEventProcessorWithJsonOutput::new(None); + let mut ep = EventProcessorWithJsonOutput::new(None); let mut changes = std::collections::HashMap::new(); changes.insert( @@ -778,7 +778,7 @@ fn patch_apply_failure_produces_item_completed_patchapply_failed() { #[test] fn task_complete_produces_turn_completed_with_usage() { - let mut ep = ExperimentalEventProcessorWithJsonOutput::new(None); + let mut ep = EventProcessorWithJsonOutput::new(None); // First, feed a TokenCount event with known totals. let usage = codex_core::protocol::TokenUsage {