mirror of
https://github.com/openai/codex.git
synced 2026-11-01 19:33:35 +00:00
simplify further
This commit is contained in:
@@ -1386,7 +1386,9 @@ mod tests {
|
||||
}),
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: turn_id.to_string(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
@@ -1457,7 +1459,9 @@ mod tests {
|
||||
})),
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-image".into(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
})),
|
||||
];
|
||||
|
||||
@@ -1772,7 +1776,9 @@ mod tests {
|
||||
}),
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
@@ -2071,7 +2077,9 @@ mod tests {
|
||||
}),
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
EventMsg::TurnStarted(TurnStartedEvent {
|
||||
turn_id: "turn-b".into(),
|
||||
@@ -2105,7 +2113,9 @@ mod tests {
|
||||
}),
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-b".into(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
@@ -2154,7 +2164,9 @@ mod tests {
|
||||
}),
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
EventMsg::TurnStarted(TurnStartedEvent {
|
||||
turn_id: "turn-b".into(),
|
||||
@@ -2188,7 +2200,9 @@ mod tests {
|
||||
}),
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-b".into(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
@@ -2357,7 +2371,9 @@ mod tests {
|
||||
}),
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
EventMsg::TurnStarted(TurnStartedEvent {
|
||||
turn_id: "turn-b".into(),
|
||||
@@ -2372,7 +2388,9 @@ mod tests {
|
||||
}),
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
EventMsg::AgentMessage(AgentMessageEvent {
|
||||
message: "still in b".into(),
|
||||
@@ -2381,7 +2399,9 @@ mod tests {
|
||||
}),
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-b".into(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
@@ -2412,7 +2432,9 @@ mod tests {
|
||||
}),
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
EventMsg::TurnStarted(TurnStartedEvent {
|
||||
turn_id: "turn-b".into(),
|
||||
@@ -2462,7 +2484,9 @@ mod tests {
|
||||
}),
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-compact".into(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
})),
|
||||
];
|
||||
|
||||
@@ -2701,7 +2725,9 @@ mod tests {
|
||||
}),
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
EventMsg::Error(ErrorEvent {
|
||||
message: "request-level failure".into(),
|
||||
@@ -2754,7 +2780,9 @@ mod tests {
|
||||
}),
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
@@ -2802,7 +2830,9 @@ mod tests {
|
||||
RolloutItem::ResponseItem(hook_prompt),
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
})),
|
||||
];
|
||||
|
||||
@@ -2847,7 +2877,9 @@ mod tests {
|
||||
}),
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
})),
|
||||
];
|
||||
|
||||
|
||||
@@ -300,8 +300,9 @@ pub(crate) async fn apply_bespoke_event_handling(
|
||||
outgoing.abort_pending_server_requests().await;
|
||||
let turn_failed = thread_state.lock().await.turn_summary.last_error.is_some()
|
||||
|| matches!(
|
||||
_ev.error(),
|
||||
Some(error) if error.affects_turn_status()
|
||||
&_ev.outcome,
|
||||
codex_protocol::protocol::TurnOutcome::Failed { error }
|
||||
if error.affects_turn_status()
|
||||
);
|
||||
thread_watch_manager
|
||||
.note_turn_completed(&conversation_id.to_string(), turn_failed)
|
||||
@@ -2120,15 +2121,19 @@ async fn handle_turn_complete(
|
||||
|
||||
let (status, error) = match turn_summary.last_error {
|
||||
Some(error) => (TurnStatus::Failed, Some(error)),
|
||||
None => match event.error() {
|
||||
Some(error) if error.affects_turn_status() => (
|
||||
TurnStatus::Failed,
|
||||
Some(TurnError {
|
||||
message: error.message.clone(),
|
||||
codex_error_info: error.codex_error_info.clone().map(Into::into),
|
||||
additional_details: None,
|
||||
}),
|
||||
),
|
||||
None => match &event.outcome {
|
||||
codex_protocol::protocol::TurnOutcome::Failed { error }
|
||||
if error.affects_turn_status() =>
|
||||
{
|
||||
(
|
||||
TurnStatus::Failed,
|
||||
Some(TurnError {
|
||||
message: error.message.clone(),
|
||||
codex_error_info: error.codex_error_info.clone().map(Into::into),
|
||||
additional_details: None,
|
||||
}),
|
||||
)
|
||||
}
|
||||
_ => (TurnStatus::Completed, None),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -250,7 +250,9 @@ async fn on_event_updates_status_from_task_started() {
|
||||
async fn on_event_updates_status_from_task_complete() {
|
||||
let status = agent_status_from_event(&EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: Some("done".to_string()),
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: Some("done".to_string()),
|
||||
},
|
||||
}));
|
||||
let expected = AgentStatus::Completed(Some("done".to_string()));
|
||||
assert_eq!(status, Some(expected));
|
||||
@@ -1133,7 +1135,9 @@ async fn multi_agent_v2_completion_ignores_dead_direct_parent() {
|
||||
tester_turn.as_ref(),
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: tester_turn.sub_id.clone(),
|
||||
last_agent_message: Some("done".to_string()),
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: Some("done".to_string()),
|
||||
},
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
@@ -1228,7 +1232,9 @@ async fn multi_agent_v2_completion_queues_message_for_direct_parent() {
|
||||
tester_turn.as_ref(),
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: tester_turn.sub_id.clone(),
|
||||
last_agent_message: Some("done".to_string()),
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: Some("done".to_string()),
|
||||
},
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
+33
-15
@@ -315,6 +315,7 @@ use crate::protocol::TokenCountEvent;
|
||||
use crate::protocol::TokenUsage;
|
||||
use crate::protocol::TokenUsageInfo;
|
||||
use crate::protocol::TurnDiffEvent;
|
||||
use crate::protocol::TurnOutcome;
|
||||
use crate::protocol::WarningEvent;
|
||||
use crate::resolve_skill_dependencies_for_turn;
|
||||
use crate::rollout::RolloutRecorder;
|
||||
@@ -335,7 +336,6 @@ use crate::tasks::GhostSnapshotTask;
|
||||
use crate::tasks::ReviewTask;
|
||||
use crate::tasks::SessionTask;
|
||||
use crate::tasks::SessionTaskContext;
|
||||
use crate::tasks::TaskCompletion;
|
||||
use crate::tools::ToolRouter;
|
||||
use crate::tools::context::SharedTurnDiffTracker;
|
||||
use crate::tools::js_repl::JsReplHandle;
|
||||
@@ -5597,9 +5597,11 @@ pub(crate) async fn run_turn(
|
||||
input: Vec<UserInput>,
|
||||
prewarmed_client_session: Option<ModelClientSession>,
|
||||
cancellation_token: CancellationToken,
|
||||
) -> TaskCompletion {
|
||||
) -> TurnOutcome {
|
||||
if input.is_empty() && !sess.has_pending_input().await {
|
||||
return TaskCompletion::Completed(None);
|
||||
return TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
};
|
||||
}
|
||||
|
||||
let model_info = turn_context.model_info.clone();
|
||||
@@ -5613,7 +5615,9 @@ pub(crate) async fn run_turn(
|
||||
.is_err()
|
||||
{
|
||||
error!("Failed to run pre-sampling compact");
|
||||
return TaskCompletion::Completed(None);
|
||||
return TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
};
|
||||
}
|
||||
|
||||
let skills_outcome = Some(turn_context.turn_skills.outcome.as_ref());
|
||||
@@ -5643,7 +5647,11 @@ pub(crate) async fn run_turn(
|
||||
.await
|
||||
{
|
||||
Ok(mcp_tools) => mcp_tools,
|
||||
Err(_) if turn_context.apps_enabled() => return TaskCompletion::Completed(None),
|
||||
Err(_) if turn_context.apps_enabled() => {
|
||||
return TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
};
|
||||
}
|
||||
Err(_) => HashMap::new(),
|
||||
}
|
||||
} else {
|
||||
@@ -5741,7 +5749,9 @@ pub(crate) async fn run_turn(
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if run_pending_session_start_hooks(&sess, &turn_context).await {
|
||||
return TaskCompletion::Completed(None);
|
||||
return TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
};
|
||||
}
|
||||
let additional_contexts = if input.is_empty() {
|
||||
Vec::new()
|
||||
@@ -5761,7 +5771,9 @@ pub(crate) async fn run_turn(
|
||||
user_prompt_submit_outcome.additional_contexts,
|
||||
)
|
||||
.await;
|
||||
return TaskCompletion::Completed(None);
|
||||
return TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
};
|
||||
}
|
||||
sess.record_user_prompt_and_emit_turn_item(turn_context.as_ref(), &input, response_item)
|
||||
.await;
|
||||
@@ -5924,7 +5936,9 @@ pub(crate) async fn run_turn(
|
||||
.await
|
||||
.is_err()
|
||||
{
|
||||
return TaskCompletion::Completed(None);
|
||||
return TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
};
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -6036,10 +6050,12 @@ pub(crate) async fn run_turn(
|
||||
}
|
||||
}
|
||||
if let Some(message) = abort_message {
|
||||
return TaskCompletion::Failed(ErrorEvent {
|
||||
message,
|
||||
codex_error_info: None,
|
||||
});
|
||||
return TurnOutcome::Failed {
|
||||
error: ErrorEvent {
|
||||
message,
|
||||
codex_error_info: None,
|
||||
},
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -6062,16 +6078,18 @@ pub(crate) async fn run_turn(
|
||||
.to_string(),
|
||||
codex_error_info: Some(CodexErrorInfo::BadRequest),
|
||||
};
|
||||
return TaskCompletion::Failed(error);
|
||||
return TurnOutcome::Failed { error };
|
||||
}
|
||||
Err(e) => {
|
||||
info!("Turn error: {e:#}");
|
||||
return TaskCompletion::Failed(e.to_error_event(/*message_prefix*/ None));
|
||||
return TurnOutcome::Failed {
|
||||
error: e.to_error_event(/*message_prefix*/ None),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TaskCompletion::Completed(last_agent_message)
|
||||
TurnOutcome::Succeeded { last_agent_message }
|
||||
}
|
||||
|
||||
async fn run_pre_sampling_compact(
|
||||
|
||||
@@ -208,7 +208,9 @@ async fn reconstruct_history_rollback_keeps_history_and_metadata_in_sync_for_com
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: first_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
},
|
||||
)),
|
||||
RolloutItem::EventMsg(EventMsg::TurnStarted(
|
||||
@@ -232,7 +234,9 @@ async fn reconstruct_history_rollback_keeps_history_and_metadata_in_sync_for_com
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: rolled_back_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
},
|
||||
)),
|
||||
RolloutItem::EventMsg(EventMsg::ThreadRolledBack(
|
||||
@@ -298,7 +302,9 @@ async fn reconstruct_history_rollback_keeps_history_and_metadata_in_sync_for_inc
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: first_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
},
|
||||
)),
|
||||
RolloutItem::EventMsg(EventMsg::TurnStarted(
|
||||
@@ -383,7 +389,9 @@ async fn reconstruct_history_rollback_skips_non_user_turns_for_history_and_metad
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: first_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
},
|
||||
)),
|
||||
RolloutItem::EventMsg(EventMsg::TurnStarted(
|
||||
@@ -406,7 +414,9 @@ async fn reconstruct_history_rollback_skips_non_user_turns_for_history_and_metad
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: second_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
},
|
||||
)),
|
||||
RolloutItem::EventMsg(EventMsg::TurnStarted(
|
||||
@@ -420,7 +430,9 @@ async fn reconstruct_history_rollback_skips_non_user_turns_for_history_and_metad
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: standalone_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
},
|
||||
)),
|
||||
RolloutItem::EventMsg(EventMsg::ThreadRolledBack(
|
||||
@@ -489,7 +501,9 @@ async fn reconstruct_history_rollback_counts_inter_agent_assistant_turns() {
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: first_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
},
|
||||
)),
|
||||
RolloutItem::EventMsg(EventMsg::TurnStarted(
|
||||
@@ -505,7 +519,9 @@ async fn reconstruct_history_rollback_counts_inter_agent_assistant_turns() {
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: assistant_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
},
|
||||
)),
|
||||
RolloutItem::EventMsg(EventMsg::ThreadRolledBack(
|
||||
@@ -569,7 +585,9 @@ async fn reconstruct_history_rollback_clears_history_and_metadata_when_exceeding
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: only_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
},
|
||||
)),
|
||||
RolloutItem::EventMsg(EventMsg::ThreadRolledBack(
|
||||
@@ -615,7 +633,9 @@ async fn record_initial_history_resumed_rollback_skips_only_user_turns() {
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: user_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
},
|
||||
)),
|
||||
// Standalone task turn (no UserMessage) should not consume rollback skips.
|
||||
@@ -629,7 +649,9 @@ async fn record_initial_history_resumed_rollback_skips_only_user_turns() {
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: standalone_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
},
|
||||
)),
|
||||
RolloutItem::EventMsg(EventMsg::ThreadRolledBack(
|
||||
@@ -679,7 +701,9 @@ async fn record_initial_history_resumed_rollback_drops_incomplete_user_turn_comp
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: previous_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
},
|
||||
)),
|
||||
RolloutItem::EventMsg(EventMsg::TurnStarted(
|
||||
@@ -831,7 +855,9 @@ async fn reconstruct_history_legacy_compaction_without_replacement_history_clear
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: current_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
},
|
||||
)),
|
||||
];
|
||||
@@ -897,7 +923,9 @@ async fn record_initial_history_resumed_turn_context_after_compaction_reestablis
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: previous_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
},
|
||||
)),
|
||||
];
|
||||
@@ -995,7 +1023,9 @@ async fn record_initial_history_resumed_aborted_turn_without_id_clears_active_tu
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: previous_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
},
|
||||
)),
|
||||
RolloutItem::EventMsg(EventMsg::TurnStarted(
|
||||
@@ -1096,7 +1126,9 @@ async fn record_initial_history_resumed_unmatched_abort_preserves_active_turn_fo
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: previous_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
},
|
||||
)),
|
||||
RolloutItem::EventMsg(EventMsg::TurnStarted(
|
||||
@@ -1124,7 +1156,9 @@ async fn record_initial_history_resumed_unmatched_abort_preserves_active_turn_fo
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: current_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
},
|
||||
)),
|
||||
];
|
||||
@@ -1203,7 +1237,9 @@ async fn record_initial_history_resumed_trailing_incomplete_turn_compaction_clea
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: previous_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
},
|
||||
)),
|
||||
RolloutItem::EventMsg(EventMsg::TurnStarted(
|
||||
@@ -1348,7 +1384,9 @@ async fn record_initial_history_resumed_replaced_incomplete_compacted_turn_clear
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: previous_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
},
|
||||
)),
|
||||
RolloutItem::EventMsg(EventMsg::TurnStarted(
|
||||
|
||||
@@ -46,6 +46,7 @@ use crate::protocol::TokenCountEvent;
|
||||
use crate::protocol::TokenUsage;
|
||||
use crate::protocol::TokenUsageInfo;
|
||||
use crate::protocol::TurnCompleteEvent;
|
||||
use crate::protocol::TurnOutcome;
|
||||
use crate::protocol::TurnStartedEvent;
|
||||
use crate::protocol::UserMessageEvent;
|
||||
use crate::rollout::policy::EventPersistenceMode;
|
||||
@@ -54,7 +55,6 @@ use crate::rollout::recorder::RolloutRecorderParams;
|
||||
use crate::state::TaskKind;
|
||||
use crate::tasks::SessionTask;
|
||||
use crate::tasks::SessionTaskContext;
|
||||
use crate::tasks::TaskCompletion;
|
||||
use crate::tools::ToolRouter;
|
||||
use crate::tools::context::FunctionToolOutput;
|
||||
use crate::tools::context::ToolInvocation;
|
||||
@@ -1486,7 +1486,9 @@ async fn thread_rollback_recomputes_previous_turn_settings_and_reference_context
|
||||
RolloutItem::ResponseItem(turn_one_assistant.clone()),
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: first_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
})),
|
||||
RolloutItem::EventMsg(EventMsg::TurnStarted(
|
||||
codex_protocol::protocol::TurnStartedEvent {
|
||||
@@ -1508,7 +1510,9 @@ async fn thread_rollback_recomputes_previous_turn_settings_and_reference_context
|
||||
RolloutItem::ResponseItem(turn_two_assistant),
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: rolled_back_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
})),
|
||||
])
|
||||
.await;
|
||||
@@ -1582,7 +1586,9 @@ async fn thread_rollback_restores_cleared_reference_context_item_after_compactio
|
||||
RolloutItem::ResponseItem(assistant_message("turn 1 assistant")),
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: first_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
})),
|
||||
RolloutItem::EventMsg(EventMsg::TurnStarted(
|
||||
codex_protocol::protocol::TurnStartedEvent {
|
||||
@@ -1597,7 +1603,9 @@ async fn thread_rollback_restores_cleared_reference_context_item_after_compactio
|
||||
}),
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: compact_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
})),
|
||||
RolloutItem::EventMsg(EventMsg::TurnStarted(
|
||||
codex_protocol::protocol::TurnStartedEvent {
|
||||
@@ -1621,7 +1629,9 @@ async fn thread_rollback_restores_cleared_reference_context_item_after_compactio
|
||||
RolloutItem::ResponseItem(assistant_message("turn 2 assistant")),
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: rolled_back_turn_id,
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
})),
|
||||
])
|
||||
.await;
|
||||
@@ -1664,7 +1674,9 @@ async fn thread_rollback_persists_marker_and_replays_cumulatively() {
|
||||
RolloutItem::ResponseItem(assistant_message("turn 1 assistant")),
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
})),
|
||||
RolloutItem::EventMsg(EventMsg::TurnStarted(
|
||||
codex_protocol::protocol::TurnStartedEvent {
|
||||
@@ -1684,7 +1696,9 @@ async fn thread_rollback_persists_marker_and_replays_cumulatively() {
|
||||
RolloutItem::ResponseItem(assistant_message("turn 2 assistant")),
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-2".to_string(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
})),
|
||||
RolloutItem::EventMsg(EventMsg::TurnStarted(
|
||||
codex_protocol::protocol::TurnStartedEvent {
|
||||
@@ -1704,7 +1718,9 @@ async fn thread_rollback_persists_marker_and_replays_cumulatively() {
|
||||
RolloutItem::ResponseItem(assistant_message("turn 3 assistant")),
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-3".to_string(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
})),
|
||||
])
|
||||
.await;
|
||||
@@ -3140,13 +3156,15 @@ async fn spawn_task_turn_span_inherits_dispatch_trace_context() {
|
||||
_ctx: Arc<TurnContext>,
|
||||
_input: Vec<UserInput>,
|
||||
_cancellation_token: CancellationToken,
|
||||
) -> TaskCompletion {
|
||||
) -> TurnOutcome {
|
||||
let mut trace = self
|
||||
.captured_trace
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
*trace = current_span_w3c_trace_context();
|
||||
TaskCompletion::Completed(None)
|
||||
TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4401,10 +4419,12 @@ impl SessionTask for NeverEndingTask {
|
||||
_ctx: Arc<TurnContext>,
|
||||
_input: Vec<UserInput>,
|
||||
cancellation_token: CancellationToken,
|
||||
) -> TaskCompletion {
|
||||
) -> TurnOutcome {
|
||||
if self.listen_to_cancellation_token {
|
||||
cancellation_token.cancelled().await;
|
||||
return TaskCompletion::Completed(None);
|
||||
return TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
};
|
||||
}
|
||||
loop {
|
||||
sleep(Duration::from_secs(60)).await;
|
||||
@@ -4428,11 +4448,13 @@ impl SessionTask for FailingTask {
|
||||
_ctx: Arc<TurnContext>,
|
||||
_input: Vec<UserInput>,
|
||||
_cancellation_token: CancellationToken,
|
||||
) -> TaskCompletion {
|
||||
TaskCompletion::Failed(ErrorEvent {
|
||||
message: "boom".to_string(),
|
||||
codex_error_info: None,
|
||||
})
|
||||
) -> TurnOutcome {
|
||||
TurnOutcome::Failed {
|
||||
error: ErrorEvent {
|
||||
message: "boom".to_string(),
|
||||
codex_error_info: None,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4557,7 +4579,9 @@ async fn task_finish_emits_turn_item_lifecycle_for_leftover_pending_user_input()
|
||||
|
||||
sess.on_task_finished(
|
||||
Arc::clone(&tc),
|
||||
TaskCompletion::Completed(/*last_agent_message*/ None),
|
||||
TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ use std::sync::Arc;
|
||||
|
||||
use super::SessionTask;
|
||||
use super::SessionTaskContext;
|
||||
use super::TaskCompletion;
|
||||
use crate::codex::TurnContext;
|
||||
use crate::protocol::TurnOutcome;
|
||||
use crate::state::TaskKind;
|
||||
use async_trait::async_trait;
|
||||
use codex_protocol::user_input::UserInput;
|
||||
@@ -28,7 +28,7 @@ impl SessionTask for CompactTask {
|
||||
ctx: Arc<TurnContext>,
|
||||
input: Vec<UserInput>,
|
||||
_cancellation_token: CancellationToken,
|
||||
) -> TaskCompletion {
|
||||
) -> TurnOutcome {
|
||||
let session = session.clone_session();
|
||||
let _ = if crate::compact::should_use_remote_compact_task(&ctx.provider) {
|
||||
let _ = session.services.session_telemetry.counter(
|
||||
@@ -45,6 +45,8 @@ impl SessionTask for CompactTask {
|
||||
);
|
||||
crate::compact::run_compact_task(session.clone(), ctx, input).await
|
||||
};
|
||||
TaskCompletion::Completed(None)
|
||||
TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use crate::codex::TurnContext;
|
||||
use crate::protocol::EventMsg;
|
||||
use crate::protocol::TurnOutcome;
|
||||
use crate::protocol::WarningEvent;
|
||||
use crate::state::TaskKind;
|
||||
use crate::tasks::SessionTask;
|
||||
use crate::tasks::SessionTaskContext;
|
||||
use crate::tasks::TaskCompletion;
|
||||
use async_trait::async_trait;
|
||||
use codex_git_utils::CreateGhostCommitOptions;
|
||||
use codex_git_utils::GhostSnapshotReport;
|
||||
@@ -43,7 +43,7 @@ impl SessionTask for GhostSnapshotTask {
|
||||
ctx: Arc<TurnContext>,
|
||||
_input: Vec<UserInput>,
|
||||
cancellation_token: CancellationToken,
|
||||
) -> TaskCompletion {
|
||||
) -> TurnOutcome {
|
||||
tokio::task::spawn(async move {
|
||||
let token = self.token;
|
||||
let warnings_enabled = !ctx.ghost_snapshot.disable_warnings;
|
||||
@@ -157,7 +157,9 @@ impl SessionTask for GhostSnapshotTask {
|
||||
Err(err) => warn!("failed to mark ghost snapshot ready: {err}"),
|
||||
}
|
||||
});
|
||||
TaskCompletion::Completed(None)
|
||||
TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,11 +29,11 @@ use crate::hook_runtime::inspect_pending_input;
|
||||
use crate::hook_runtime::record_additional_contexts;
|
||||
use crate::hook_runtime::record_pending_input;
|
||||
use crate::models_manager::manager::ModelsManager;
|
||||
use crate::protocol::ErrorEvent;
|
||||
use crate::protocol::EventMsg;
|
||||
use crate::protocol::TurnAbortReason;
|
||||
use crate::protocol::TurnAbortedEvent;
|
||||
use crate::protocol::TurnCompleteEvent;
|
||||
use crate::protocol::TurnOutcome;
|
||||
use crate::state::ActiveTurn;
|
||||
use crate::state::RunningTask;
|
||||
use crate::state::TaskKind;
|
||||
@@ -100,11 +100,6 @@ pub(crate) struct SessionTaskContext {
|
||||
session: Arc<Session>,
|
||||
}
|
||||
|
||||
pub(crate) enum TaskCompletion {
|
||||
Completed(Option<String>),
|
||||
Failed(ErrorEvent),
|
||||
}
|
||||
|
||||
impl SessionTaskContext {
|
||||
pub(crate) fn new(session: Arc<Session>) -> Self {
|
||||
Self { session }
|
||||
@@ -146,7 +141,7 @@ pub(crate) trait SessionTask: Send + Sync + 'static {
|
||||
/// `ctx`, returning an optional final agent message when finished. The
|
||||
/// provided `cancellation_token` is cancelled when the session requests an
|
||||
/// abort; implementers should watch for it and terminate quickly once it
|
||||
/// fires. The returned [`TaskCompletion`] determines the single terminal
|
||||
/// fires. The returned [`TurnOutcome`] determines the single terminal
|
||||
/// event emitted by [`Session::on_task_finished`].
|
||||
async fn run(
|
||||
self: Arc<Self>,
|
||||
@@ -154,7 +149,7 @@ pub(crate) trait SessionTask: Send + Sync + 'static {
|
||||
ctx: Arc<TurnContext>,
|
||||
input: Vec<UserInput>,
|
||||
cancellation_token: CancellationToken,
|
||||
) -> TaskCompletion;
|
||||
) -> TurnOutcome;
|
||||
|
||||
/// Gives the task a chance to perform cleanup after an abort.
|
||||
///
|
||||
@@ -320,7 +315,7 @@ impl Session {
|
||||
pub async fn on_task_finished(
|
||||
self: &Arc<Self>,
|
||||
turn_context: Arc<TurnContext>,
|
||||
completion: TaskCompletion,
|
||||
outcome: TurnOutcome,
|
||||
) {
|
||||
turn_context
|
||||
.turn_metadata_state
|
||||
@@ -437,15 +432,10 @@ impl Session {
|
||||
&[("token_type", "reasoning_output"), tmp_mem],
|
||||
);
|
||||
}
|
||||
let event = match completion {
|
||||
TaskCompletion::Completed(last_agent_message) => EventMsg::TurnComplete(
|
||||
TurnCompleteEvent::succeeded(turn_context.sub_id.clone(), last_agent_message),
|
||||
),
|
||||
TaskCompletion::Failed(error) => EventMsg::TurnComplete(TurnCompleteEvent::failed(
|
||||
turn_context.sub_id.clone(),
|
||||
error,
|
||||
)),
|
||||
};
|
||||
let event = EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: turn_context.sub_id.clone(),
|
||||
outcome,
|
||||
});
|
||||
self.send_event(turn_context.as_ref(), event).await;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::codex::TurnContext;
|
||||
use crate::codex::run_turn;
|
||||
use crate::protocol::EventMsg;
|
||||
use crate::protocol::TurnStartedEvent;
|
||||
use crate::protocol::TurnOutcome;
|
||||
use crate::session_startup_prewarm::SessionStartupPrewarmResolution;
|
||||
use crate::state::TaskKind;
|
||||
use codex_protocol::user_input::UserInput;
|
||||
@@ -15,7 +16,6 @@ use tracing::trace_span;
|
||||
|
||||
use super::SessionTask;
|
||||
use super::SessionTaskContext;
|
||||
use super::TaskCompletion;
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct RegularTask;
|
||||
@@ -42,7 +42,7 @@ impl SessionTask for RegularTask {
|
||||
ctx: Arc<TurnContext>,
|
||||
input: Vec<UserInput>,
|
||||
cancellation_token: CancellationToken,
|
||||
) -> TaskCompletion {
|
||||
) -> TurnOutcome {
|
||||
let sess = session.clone_session();
|
||||
let run_turn_span = trace_span!("run_turn");
|
||||
// Regular turns emit `TurnStarted` inline so first-turn lifecycle does
|
||||
@@ -59,7 +59,9 @@ impl SessionTask for RegularTask {
|
||||
.await
|
||||
{
|
||||
SessionStartupPrewarmResolution::Cancelled => {
|
||||
return TaskCompletion::Completed(None);
|
||||
return TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
};
|
||||
}
|
||||
SessionStartupPrewarmResolution::Unavailable { .. } => None,
|
||||
SessionStartupPrewarmResolution::Ready(prewarmed_client_session) => {
|
||||
|
||||
@@ -32,7 +32,6 @@ use std::sync::LazyLock;
|
||||
|
||||
use super::SessionTask;
|
||||
use super::SessionTaskContext;
|
||||
use super::TaskCompletion;
|
||||
|
||||
static REVIEW_EXIT_SUCCESS_TEMPLATE: LazyLock<Template> = LazyLock::new(|| {
|
||||
let normalized =
|
||||
@@ -66,7 +65,7 @@ impl SessionTask for ReviewTask {
|
||||
ctx: Arc<TurnContext>,
|
||||
input: Vec<UserInput>,
|
||||
cancellation_token: CancellationToken,
|
||||
) -> TaskCompletion {
|
||||
) -> TurnOutcome {
|
||||
let _ = session.session.services.session_telemetry.counter(
|
||||
"codex.task.review",
|
||||
/*inc*/ 1,
|
||||
@@ -88,7 +87,9 @@ impl SessionTask for ReviewTask {
|
||||
if !cancellation_token.is_cancelled() {
|
||||
exit_review_mode(session.clone_session(), output.clone(), ctx.clone()).await;
|
||||
}
|
||||
TaskCompletion::Completed(None)
|
||||
TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
}
|
||||
}
|
||||
|
||||
async fn abort(&self, session: Arc<SessionTaskContext>, ctx: Arc<TurnContext>) {
|
||||
|
||||
@@ -4,10 +4,10 @@ use crate::codex::TurnContext;
|
||||
use crate::protocol::EventMsg;
|
||||
use crate::protocol::UndoCompletedEvent;
|
||||
use crate::protocol::UndoStartedEvent;
|
||||
use crate::protocol::TurnOutcome;
|
||||
use crate::state::TaskKind;
|
||||
use crate::tasks::SessionTask;
|
||||
use crate::tasks::SessionTaskContext;
|
||||
use crate::tasks::TaskCompletion;
|
||||
use async_trait::async_trait;
|
||||
use codex_git_utils::RestoreGhostCommitOptions;
|
||||
use codex_git_utils::restore_ghost_commit_with_options;
|
||||
@@ -42,7 +42,7 @@ impl SessionTask for UndoTask {
|
||||
ctx: Arc<TurnContext>,
|
||||
_input: Vec<UserInput>,
|
||||
cancellation_token: CancellationToken,
|
||||
) -> TaskCompletion {
|
||||
) -> TurnOutcome {
|
||||
let _ = session.session.services.session_telemetry.counter(
|
||||
"codex.task.undo",
|
||||
/*inc*/ 1,
|
||||
@@ -66,7 +66,9 @@ impl SessionTask for UndoTask {
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
return TaskCompletion::Completed(None);
|
||||
return TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
};
|
||||
}
|
||||
|
||||
let history = sess.clone_history().await;
|
||||
@@ -91,7 +93,9 @@ impl SessionTask for UndoTask {
|
||||
completed.message = Some("No ghost snapshot available to undo.".to_string());
|
||||
sess.send_event(ctx.as_ref(), EventMsg::UndoCompleted(completed))
|
||||
.await;
|
||||
return TaskCompletion::Completed(None);
|
||||
return TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
};
|
||||
};
|
||||
|
||||
let commit_id = ghost_commit.id().to_string();
|
||||
@@ -127,6 +131,8 @@ impl SessionTask for UndoTask {
|
||||
|
||||
sess.send_event(ctx.as_ref(), EventMsg::UndoCompleted(completed))
|
||||
.await;
|
||||
TaskCompletion::Completed(None)
|
||||
TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ use crate::protocol::ExecCommandSource;
|
||||
use crate::protocol::ExecCommandStatus;
|
||||
use crate::protocol::SandboxPolicy;
|
||||
use crate::protocol::TurnStartedEvent;
|
||||
use crate::protocol::TurnOutcome;
|
||||
use crate::sandboxing::ExecRequest;
|
||||
use crate::state::TaskKind;
|
||||
use crate::tools::format_exec_output_str;
|
||||
@@ -33,7 +34,6 @@ use codex_sandboxing::SandboxType;
|
||||
|
||||
use super::SessionTask;
|
||||
use super::SessionTaskContext;
|
||||
use super::TaskCompletion;
|
||||
use crate::codex::Session;
|
||||
use codex_protocol::models::ResponseInputItem;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
@@ -79,7 +79,7 @@ impl SessionTask for UserShellCommandTask {
|
||||
turn_context: Arc<TurnContext>,
|
||||
_input: Vec<UserInput>,
|
||||
cancellation_token: CancellationToken,
|
||||
) -> TaskCompletion {
|
||||
) -> TurnOutcome {
|
||||
execute_user_shell_command(
|
||||
session.clone_session(),
|
||||
turn_context,
|
||||
@@ -88,7 +88,9 @@ impl SessionTask for UserShellCommandTask {
|
||||
UserShellCommandMode::StandaloneTurn,
|
||||
)
|
||||
.await;
|
||||
TaskCompletion::Completed(None)
|
||||
TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,10 +18,10 @@ use crate::protocol::SandboxPolicy;
|
||||
use crate::protocol::SessionSource;
|
||||
use crate::protocol::SubAgentSource;
|
||||
use crate::protocol::TurnCompleteEvent;
|
||||
use crate::protocol::TurnOutcome;
|
||||
use crate::state::TaskKind;
|
||||
use crate::tasks::SessionTask;
|
||||
use crate::tasks::SessionTaskContext;
|
||||
use crate::tasks::TaskCompletion;
|
||||
use crate::tools::context::ToolOutput;
|
||||
use crate::tools::handlers::multi_agents_v2::AssignTaskHandler as AssignTaskHandlerV2;
|
||||
use crate::tools::handlers::multi_agents_v2::CloseAgentHandler as CloseAgentHandlerV2;
|
||||
@@ -133,9 +133,11 @@ impl SessionTask for NeverEndingTask {
|
||||
_ctx: Arc<TurnContext>,
|
||||
_input: Vec<UserInput>,
|
||||
cancellation_token: CancellationToken,
|
||||
) -> TaskCompletion {
|
||||
) -> TurnOutcome {
|
||||
cancellation_token.cancelled().await;
|
||||
TaskCompletion::Completed(None)
|
||||
TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,11 +157,13 @@ impl SessionTask for FailingTask {
|
||||
_ctx: Arc<TurnContext>,
|
||||
_input: Vec<UserInput>,
|
||||
_cancellation_token: CancellationToken,
|
||||
) -> TaskCompletion {
|
||||
TaskCompletion::Failed(ErrorEvent {
|
||||
message: "boom".to_string(),
|
||||
codex_error_info: None,
|
||||
})
|
||||
) -> TurnOutcome {
|
||||
TurnOutcome::Failed {
|
||||
error: ErrorEvent {
|
||||
message: "boom".to_string(),
|
||||
codex_error_info: None,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -630,7 +634,9 @@ async fn multi_agent_v2_list_agents_returns_completed_status_and_last_task_messa
|
||||
child_turn.as_ref(),
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: child_turn.sub_id.clone(),
|
||||
last_agent_message: Some("done".to_string()),
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: Some("done".to_string()),
|
||||
},
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
@@ -1196,7 +1202,9 @@ async fn multi_agent_v2_assign_task_completion_notifies_parent_after_reuse() {
|
||||
first_turn.as_ref(),
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: first_turn.sub_id.clone(),
|
||||
last_agent_message: Some("done once".to_string()),
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: Some("done once".to_string()),
|
||||
},
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
@@ -1222,7 +1230,9 @@ async fn multi_agent_v2_assign_task_completion_notifies_parent_after_reuse() {
|
||||
second_turn.as_ref(),
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: second_turn.sub_id.clone(),
|
||||
last_agent_message: Some("done twice".to_string()),
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: Some("done twice".to_string()),
|
||||
},
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
@@ -1319,7 +1329,9 @@ async fn multi_agent_v2_failed_turn_forwards_only_error_status_after_reuse() {
|
||||
first_turn.as_ref(),
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: first_turn.sub_id.clone(),
|
||||
last_agent_message: Some("done once".to_string()),
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: Some("done once".to_string()),
|
||||
},
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -134,7 +134,7 @@ async fn resume_includes_initial_messages_from_rollout_events() -> Result<()> {
|
||||
assert_eq!(assistant_message.message, "Completed first turn");
|
||||
assert_eq!(completed.turn_id, started.turn_id);
|
||||
assert_eq!(
|
||||
completed.last_agent_message.as_deref(),
|
||||
completed.last_agent_message().as_deref(),
|
||||
Some("Completed first turn")
|
||||
);
|
||||
}
|
||||
@@ -224,7 +224,7 @@ async fn resume_includes_initial_messages_from_reasoning_events() -> Result<()>
|
||||
assert_eq!(assistant_message.message, "Completed reasoning turn");
|
||||
assert_eq!(completed.turn_id, started.turn_id);
|
||||
assert_eq!(
|
||||
completed.last_agent_message.as_deref(),
|
||||
completed.last_agent_message().as_deref(),
|
||||
Some("Completed reasoning turn")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1872,36 +1872,6 @@ pub struct TurnCompleteEvent {
|
||||
pub outcome: TurnOutcome,
|
||||
}
|
||||
|
||||
impl TurnCompleteEvent {
|
||||
pub fn succeeded(turn_id: String, last_agent_message: Option<String>) -> Self {
|
||||
Self {
|
||||
turn_id,
|
||||
outcome: TurnOutcome::Succeeded { last_agent_message },
|
||||
}
|
||||
}
|
||||
|
||||
pub fn failed(turn_id: String, error: ErrorEvent) -> Self {
|
||||
Self {
|
||||
turn_id,
|
||||
outcome: TurnOutcome::Failed { error },
|
||||
}
|
||||
}
|
||||
|
||||
pub fn last_agent_message(&self) -> Option<&str> {
|
||||
match &self.outcome {
|
||||
TurnOutcome::Succeeded { last_agent_message } => last_agent_message.as_deref(),
|
||||
TurnOutcome::Failed { .. } => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error(&self) -> Option<&ErrorEvent> {
|
||||
match &self.outcome {
|
||||
TurnOutcome::Succeeded { .. } => None,
|
||||
TurnOutcome::Failed { error } => Some(error),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, TS)]
|
||||
pub struct TurnStartedEvent {
|
||||
pub turn_id: String,
|
||||
|
||||
@@ -103,6 +103,8 @@ use codex_protocol::protocol::TurnAbortedEvent;
|
||||
#[cfg(test)]
|
||||
use codex_protocol::protocol::TurnCompleteEvent;
|
||||
#[cfg(test)]
|
||||
use codex_protocol::protocol::TurnOutcome;
|
||||
#[cfg(test)]
|
||||
use codex_protocol::protocol::TurnStartedEvent;
|
||||
#[cfg(test)]
|
||||
use std::time::Duration;
|
||||
@@ -738,10 +740,12 @@ fn append_terminal_turn_events(events: &mut Vec<Event>, turn: &Turn, include_fai
|
||||
match turn.status {
|
||||
TurnStatus::Completed => events.push(Event {
|
||||
id: String::new(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent::succeeded(
|
||||
turn.id.clone(),
|
||||
/*last_agent_message*/ None,
|
||||
)),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: turn.id.clone(),
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
TurnStatus::Interrupted => events.push(Event {
|
||||
id: String::new(),
|
||||
@@ -754,9 +758,10 @@ fn append_terminal_turn_events(events: &mut Vec<Event>, turn: &Turn, include_fai
|
||||
let _ = include_failed_error;
|
||||
events.push(Event {
|
||||
id: String::new(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent::failed(
|
||||
turn.id.clone(),
|
||||
ErrorEvent {
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: turn.id.clone(),
|
||||
outcome: TurnOutcome::Failed {
|
||||
error: ErrorEvent {
|
||||
message: turn
|
||||
.error
|
||||
.as_ref()
|
||||
@@ -769,7 +774,8 @@ fn append_terminal_turn_events(events: &mut Vec<Event>, turn: &Turn, include_fai
|
||||
.and_then(app_server_codex_error_info_to_core)
|
||||
}),
|
||||
},
|
||||
)),
|
||||
},
|
||||
}),
|
||||
});
|
||||
}
|
||||
TurnStatus::InProgress => {
|
||||
@@ -1121,7 +1127,7 @@ mod tests {
|
||||
panic!("expected turn complete event");
|
||||
};
|
||||
assert_eq!(completed.turn_id, turn_id);
|
||||
assert_eq!(completed.last_agent_message, None);
|
||||
assert_eq!(completed.last_agent_message(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1367,7 +1373,7 @@ mod tests {
|
||||
panic!("expected turn complete event");
|
||||
};
|
||||
assert_eq!(completed.turn_id, turn_id);
|
||||
assert_eq!(completed.last_agent_message, None);
|
||||
assert_eq!(completed.last_agent_message(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -193,10 +193,8 @@ use codex_protocol::protocol::TerminalInteractionEvent;
|
||||
use codex_protocol::protocol::TokenUsage;
|
||||
use codex_protocol::protocol::TokenUsageInfo;
|
||||
use codex_protocol::protocol::TurnAbortReason;
|
||||
use codex_protocol::protocol::TurnCompleteEvent;
|
||||
#[cfg(test)]
|
||||
use codex_protocol::protocol::TurnDiffEvent;
|
||||
use codex_protocol::protocol::TurnOutcome;
|
||||
#[cfg(test)]
|
||||
use codex_protocol::protocol::UndoCompletedEvent;
|
||||
#[cfg(test)]
|
||||
@@ -6927,14 +6925,16 @@ impl ChatWidget {
|
||||
self.on_task_started();
|
||||
}
|
||||
}
|
||||
EventMsg::TurnComplete(TurnCompleteEvent { outcome, .. }) => match outcome {
|
||||
TurnOutcome::Succeeded { last_agent_message } => {
|
||||
EventMsg::TurnComplete(codex_protocol::protocol::TurnCompleteEvent { outcome, .. }) => {
|
||||
match outcome {
|
||||
codex_protocol::protocol::TurnOutcome::Succeeded { last_agent_message } => {
|
||||
self.on_task_complete(last_agent_message, from_replay);
|
||||
}
|
||||
TurnOutcome::Failed { error } => {
|
||||
self.on_error(error.message);
|
||||
codex_protocol::protocol::TurnOutcome::Failed { error } => {
|
||||
self.on_error(error.message);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
EventMsg::TokenCount(ev) => {
|
||||
self.set_token_info(ev.info);
|
||||
self.on_rate_limit_snapshot(ev.rate_limits);
|
||||
|
||||
@@ -1741,7 +1741,9 @@ async fn steer_rejection_queues_review_follow_up_before_existing_queued_messages
|
||||
id: "turn-complete".into(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -1760,7 +1762,9 @@ async fn steer_rejection_queues_review_follow_up_before_existing_queued_messages
|
||||
id: "turn-complete-2".into(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-2".to_string(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -3275,7 +3279,9 @@ async fn plan_implementation_popup_skips_replayed_turn_complete() {
|
||||
|
||||
chat.replay_initial_messages(vec![EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: Some("Plan details".to_string()),
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: Some("Plan details".to_string()),
|
||||
},
|
||||
})]);
|
||||
|
||||
let popup = render_bottom_popup(&chat, /*width*/ 80);
|
||||
@@ -3299,7 +3305,9 @@ async fn plan_implementation_popup_shows_once_when_replay_precedes_live_turn_com
|
||||
|
||||
chat.replay_initial_messages(vec![EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: Some("Plan details".to_string()),
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: Some("Plan details".to_string()),
|
||||
},
|
||||
})]);
|
||||
let replay_popup = render_bottom_popup(&chat, /*width*/ 80);
|
||||
assert!(
|
||||
@@ -3311,7 +3319,9 @@ async fn plan_implementation_popup_shows_once_when_replay_precedes_live_turn_com
|
||||
id: "live-turn-complete-1".to_string(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: Some("Plan details".to_string()),
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: Some("Plan details".to_string()),
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -3332,7 +3342,9 @@ async fn plan_implementation_popup_shows_once_when_replay_precedes_live_turn_com
|
||||
id: "live-turn-complete-2".to_string(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: Some("Plan details".to_string()),
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: Some("Plan details".to_string()),
|
||||
},
|
||||
}),
|
||||
});
|
||||
let duplicate_popup = render_bottom_popup(&chat, /*width*/ 80);
|
||||
@@ -6463,7 +6475,9 @@ async fn unified_exec_wait_after_final_agent_message_snapshot() {
|
||||
id: "turn-1".into(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: Some("Final response.".into()),
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: Some("Final response.".into()),
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -6505,7 +6519,9 @@ async fn unified_exec_wait_before_streamed_agent_message_snapshot() {
|
||||
id: "turn-1".into(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -6570,7 +6586,9 @@ async fn unified_exec_waiting_multiple_empty_snapshots() {
|
||||
id: "turn-wait-1".into(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -6648,7 +6666,9 @@ async fn unified_exec_non_empty_then_empty_snapshots() {
|
||||
id: "turn-wait-3".into(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -7150,7 +7170,9 @@ async fn slash_copy_state_tracks_turn_complete_final_reply() {
|
||||
id: "turn-1".into(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: Some("Final reply **markdown**".to_string()),
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: Some("Final reply **markdown**".to_string()),
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -7180,7 +7202,9 @@ async fn slash_copy_state_tracks_plan_item_completion() {
|
||||
id: "turn-1".into(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -7213,7 +7237,9 @@ async fn slash_copy_state_is_preserved_during_running_task() {
|
||||
id: "turn-1".into(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: Some("Previous completed reply".to_string()),
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: Some("Previous completed reply".to_string()),
|
||||
},
|
||||
}),
|
||||
});
|
||||
chat.on_task_started();
|
||||
@@ -7232,7 +7258,9 @@ async fn slash_copy_state_clears_on_thread_rollback() {
|
||||
id: "turn-1".into(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: Some("Reply that will be rolled back".to_string()),
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: Some("Reply that will be rolled back".to_string()),
|
||||
},
|
||||
}),
|
||||
});
|
||||
chat.handle_codex_event(Event {
|
||||
@@ -7260,7 +7288,9 @@ async fn slash_copy_is_unavailable_when_legacy_agent_message_is_not_repeated_on_
|
||||
id: "turn-1".into(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
});
|
||||
let _ = drain_insert_history(&mut rx);
|
||||
@@ -7301,7 +7331,9 @@ async fn slash_copy_uses_agent_message_item_when_turn_complete_omits_final_text(
|
||||
id: "turn-1".into(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
});
|
||||
let _ = drain_insert_history(&mut rx);
|
||||
@@ -7346,7 +7378,9 @@ async fn slash_copy_does_not_return_stale_output_after_thread_rollback() {
|
||||
id: "turn-1".into(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
});
|
||||
let _ = drain_insert_history(&mut rx);
|
||||
@@ -11230,7 +11264,9 @@ async fn turn_complete_keeps_unified_exec_processes() {
|
||||
id: "turn-1".into(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -13172,7 +13208,9 @@ async fn status_line_branch_refreshes_after_turn_complete() {
|
||||
id: "turn-1".into(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -13474,7 +13512,9 @@ async fn multiple_agent_messages_in_single_turn_emit_multiple_headers() {
|
||||
id: "s1".into(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -13945,7 +13985,9 @@ printf 'fenced within fenced\n'
|
||||
id: "t1".into(),
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: None,
|
||||
outcome: TurnOutcome::Succeeded {
|
||||
last_agent_message: None,
|
||||
},
|
||||
}),
|
||||
});
|
||||
for lines in drain_insert_history(&mut rx) {
|
||||
|
||||
Reference in New Issue
Block a user