mirror of
https://github.com/openai/codex.git
synced 2026-05-04 05:11:37 +03:00
Allow --output-last-message to print to stdout
This commit is contained in:
@@ -51,7 +51,7 @@ fn event(id: &str, msg: EventMsg) -> Event {
|
||||
|
||||
#[test]
|
||||
fn session_configured_produces_thread_started_event() {
|
||||
let mut ep = EventProcessorWithJsonOutput::new(None);
|
||||
let mut ep = EventProcessorWithJsonOutput::default();
|
||||
let session_id =
|
||||
codex_protocol::ConversationId::from_string("67e55044-10b1-426f-9247-bb680e5fe0c8")
|
||||
.unwrap();
|
||||
@@ -79,7 +79,7 @@ fn session_configured_produces_thread_started_event() {
|
||||
|
||||
#[test]
|
||||
fn task_started_produces_turn_started_event() {
|
||||
let mut ep = EventProcessorWithJsonOutput::new(None);
|
||||
let mut ep = EventProcessorWithJsonOutput::default();
|
||||
let out = ep.collect_thread_events(&event(
|
||||
"t1",
|
||||
EventMsg::TaskStarted(codex_core::protocol::TaskStartedEvent {
|
||||
@@ -92,7 +92,7 @@ fn task_started_produces_turn_started_event() {
|
||||
|
||||
#[test]
|
||||
fn web_search_end_emits_item_completed() {
|
||||
let mut ep = EventProcessorWithJsonOutput::new(None);
|
||||
let mut ep = EventProcessorWithJsonOutput::default();
|
||||
let query = "rust async await".to_string();
|
||||
let out = ep.collect_thread_events(&event(
|
||||
"w1",
|
||||
@@ -119,7 +119,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 = EventProcessorWithJsonOutput::new(None);
|
||||
let mut ep = EventProcessorWithJsonOutput::default();
|
||||
|
||||
// First plan update => item.started (todo_list)
|
||||
let first = event(
|
||||
@@ -236,7 +236,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 = EventProcessorWithJsonOutput::new(None);
|
||||
let mut ep = EventProcessorWithJsonOutput::default();
|
||||
let invocation = McpInvocation {
|
||||
server: "server_a".to_string(),
|
||||
tool: "tool_x".to_string(),
|
||||
@@ -296,7 +296,7 @@ fn mcp_tool_call_begin_and_end_emit_item_events() {
|
||||
|
||||
#[test]
|
||||
fn mcp_tool_call_failure_sets_failed_status() {
|
||||
let mut ep = EventProcessorWithJsonOutput::new(None);
|
||||
let mut ep = EventProcessorWithJsonOutput::default();
|
||||
let invocation = McpInvocation {
|
||||
server: "server_b".to_string(),
|
||||
tool: "tool_y".to_string(),
|
||||
@@ -343,7 +343,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 = EventProcessorWithJsonOutput::new(None);
|
||||
let mut ep = EventProcessorWithJsonOutput::default();
|
||||
|
||||
// First turn: start + complete
|
||||
let start = event(
|
||||
@@ -388,7 +388,7 @@ fn plan_update_after_complete_starts_new_todo_list_with_new_id() {
|
||||
|
||||
#[test]
|
||||
fn agent_reasoning_produces_item_completed_reasoning() {
|
||||
let mut ep = EventProcessorWithJsonOutput::new(None);
|
||||
let mut ep = EventProcessorWithJsonOutput::default();
|
||||
let ev = event(
|
||||
"e1",
|
||||
EventMsg::AgentReasoning(AgentReasoningEvent {
|
||||
@@ -411,7 +411,7 @@ fn agent_reasoning_produces_item_completed_reasoning() {
|
||||
|
||||
#[test]
|
||||
fn agent_message_produces_item_completed_assistant_message() {
|
||||
let mut ep = EventProcessorWithJsonOutput::new(None);
|
||||
let mut ep = EventProcessorWithJsonOutput::default();
|
||||
let ev = event(
|
||||
"e1",
|
||||
EventMsg::AgentMessage(AgentMessageEvent {
|
||||
@@ -434,7 +434,7 @@ fn agent_message_produces_item_completed_assistant_message() {
|
||||
|
||||
#[test]
|
||||
fn error_event_produces_error() {
|
||||
let mut ep = EventProcessorWithJsonOutput::new(None);
|
||||
let mut ep = EventProcessorWithJsonOutput::default();
|
||||
let out = ep.collect_thread_events(&event(
|
||||
"e1",
|
||||
EventMsg::Error(codex_core::protocol::ErrorEvent {
|
||||
@@ -451,7 +451,7 @@ fn error_event_produces_error() {
|
||||
|
||||
#[test]
|
||||
fn stream_error_event_produces_error() {
|
||||
let mut ep = EventProcessorWithJsonOutput::new(None);
|
||||
let mut ep = EventProcessorWithJsonOutput::default();
|
||||
let out = ep.collect_thread_events(&event(
|
||||
"e1",
|
||||
EventMsg::StreamError(codex_core::protocol::StreamErrorEvent {
|
||||
@@ -468,7 +468,7 @@ fn stream_error_event_produces_error() {
|
||||
|
||||
#[test]
|
||||
fn error_followed_by_task_complete_produces_turn_failed() {
|
||||
let mut ep = EventProcessorWithJsonOutput::new(None);
|
||||
let mut ep = EventProcessorWithJsonOutput::default();
|
||||
|
||||
let error_event = event(
|
||||
"e1",
|
||||
@@ -501,7 +501,7 @@ fn error_followed_by_task_complete_produces_turn_failed() {
|
||||
|
||||
#[test]
|
||||
fn exec_command_end_success_produces_completed_command_item() {
|
||||
let mut ep = EventProcessorWithJsonOutput::new(None);
|
||||
let mut ep = EventProcessorWithJsonOutput::default();
|
||||
|
||||
// Begin -> no output
|
||||
let begin = event(
|
||||
@@ -561,7 +561,7 @@ fn exec_command_end_success_produces_completed_command_item() {
|
||||
|
||||
#[test]
|
||||
fn exec_command_end_failure_produces_failed_command_item() {
|
||||
let mut ep = EventProcessorWithJsonOutput::new(None);
|
||||
let mut ep = EventProcessorWithJsonOutput::default();
|
||||
|
||||
// Begin -> no output
|
||||
let begin = event(
|
||||
@@ -620,7 +620,7 @@ fn exec_command_end_failure_produces_failed_command_item() {
|
||||
|
||||
#[test]
|
||||
fn exec_command_end_without_begin_is_ignored() {
|
||||
let mut ep = EventProcessorWithJsonOutput::new(None);
|
||||
let mut ep = EventProcessorWithJsonOutput::default();
|
||||
|
||||
// End event arrives without a prior Begin; should produce no thread events.
|
||||
let end_only = event(
|
||||
@@ -641,7 +641,7 @@ fn exec_command_end_without_begin_is_ignored() {
|
||||
|
||||
#[test]
|
||||
fn patch_apply_success_produces_item_completed_patchapply() {
|
||||
let mut ep = EventProcessorWithJsonOutput::new(None);
|
||||
let mut ep = EventProcessorWithJsonOutput::default();
|
||||
|
||||
// Prepare a patch with multiple kinds of changes
|
||||
let mut changes = std::collections::HashMap::new();
|
||||
@@ -723,7 +723,7 @@ fn patch_apply_success_produces_item_completed_patchapply() {
|
||||
|
||||
#[test]
|
||||
fn patch_apply_failure_produces_item_completed_patchapply_failed() {
|
||||
let mut ep = EventProcessorWithJsonOutput::new(None);
|
||||
let mut ep = EventProcessorWithJsonOutput::default();
|
||||
|
||||
let mut changes = std::collections::HashMap::new();
|
||||
changes.insert(
|
||||
@@ -777,7 +777,7 @@ fn patch_apply_failure_produces_item_completed_patchapply_failed() {
|
||||
|
||||
#[test]
|
||||
fn task_complete_produces_turn_completed_with_usage() {
|
||||
let mut ep = EventProcessorWithJsonOutput::new(None);
|
||||
let mut ep = EventProcessorWithJsonOutput::default();
|
||||
|
||||
// First, feed a TokenCount event with known totals.
|
||||
let usage = codex_core::protocol::TokenUsage {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Aggregates all former standalone integration tests as modules.
|
||||
mod apply_patch;
|
||||
mod output_last_message;
|
||||
mod output_schema;
|
||||
mod resume;
|
||||
mod sandbox;
|
||||
|
||||
106
codex-rs/exec/tests/suite/output_last_message.rs
Normal file
106
codex-rs/exec/tests/suite/output_last_message.rs
Normal file
@@ -0,0 +1,106 @@
|
||||
#![cfg(not(target_os = "windows"))]
|
||||
#![allow(clippy::expect_used, clippy::unwrap_used)]
|
||||
|
||||
use core_test_support::responses;
|
||||
use core_test_support::test_codex_exec::test_codex_exec;
|
||||
use wiremock::matchers::any;
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn exec_includes_output_last_message_in_request() -> anyhow::Result<()> {
|
||||
let test = test_codex_exec();
|
||||
|
||||
let last_message_path = test.cwd_path().join("last_message.txt");
|
||||
let server = responses::start_mock_server().await;
|
||||
let body = responses::sse(vec![
|
||||
serde_json::json!({
|
||||
"type": "response.created",
|
||||
"response": {"id": "resp1"}
|
||||
}),
|
||||
responses::ev_assistant_message("m1", "fixture hello"),
|
||||
responses::ev_completed("resp1"),
|
||||
]);
|
||||
responses::mount_sse_once_match(&server, any(), body).await;
|
||||
|
||||
test.cmd_with_server(&server)
|
||||
.arg("--skip-git-repo-check")
|
||||
// keep using -C in the test to exercise the flag as well
|
||||
.arg("-C")
|
||||
.arg(test.cwd_path())
|
||||
.arg("--output-last-message")
|
||||
.arg(&last_message_path)
|
||||
.arg("tell me a joke")
|
||||
.assert()
|
||||
.success();
|
||||
|
||||
assert_eq!(
|
||||
std::fs::read_to_string(&last_message_path)?,
|
||||
"fixture hello"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn exec_includes_output_last_message_in_request_json() -> anyhow::Result<()> {
|
||||
let test = test_codex_exec();
|
||||
|
||||
let last_message_path = test.cwd_path().join("last_message.txt");
|
||||
let server = responses::start_mock_server().await;
|
||||
let body = responses::sse(vec![
|
||||
serde_json::json!({
|
||||
"type": "response.created",
|
||||
"response": {"id": "resp1"}
|
||||
}),
|
||||
responses::ev_assistant_message("m1", "fixture hello"),
|
||||
responses::ev_completed("resp1"),
|
||||
]);
|
||||
responses::mount_sse_once_match(&server, any(), body).await;
|
||||
|
||||
test.cmd_with_server(&server)
|
||||
.arg("--skip-git-repo-check")
|
||||
// keep using -C in the test to exercise the flag as well
|
||||
.arg("-C")
|
||||
.arg(test.cwd_path())
|
||||
.arg("--output-last-message")
|
||||
.arg(&last_message_path)
|
||||
.arg("--json")
|
||||
.arg("tell me a joke")
|
||||
.assert()
|
||||
.success();
|
||||
|
||||
assert_eq!(
|
||||
std::fs::read_to_string(&last_message_path)?,
|
||||
"fixture hello"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn exec_includes_output_last_message_in_request_stdout() -> anyhow::Result<()> {
|
||||
let test = test_codex_exec();
|
||||
|
||||
let server = responses::start_mock_server().await;
|
||||
let body = responses::sse(vec![
|
||||
serde_json::json!({
|
||||
"type": "response.created",
|
||||
"response": {"id": "resp1"}
|
||||
}),
|
||||
responses::ev_assistant_message("m1", "fixture hello"),
|
||||
responses::ev_completed("resp1"),
|
||||
]);
|
||||
responses::mount_sse_once_match(&server, any(), body).await;
|
||||
|
||||
test.cmd_with_server(&server)
|
||||
.arg("--skip-git-repo-check")
|
||||
// keep using -C in the test to exercise the flag as well
|
||||
.arg("-C")
|
||||
.arg(test.cwd_path())
|
||||
.arg("tell me a joke")
|
||||
.arg("--output-last-message")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout("fixture hello\n");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user