mirror of
https://github.com/openai/codex.git
synced 2026-10-20 17:38:45 +00:00
add turn completion model identity fields
This commit is contained in:
@@ -356,6 +356,8 @@ fn sample_turn_completed_notification(
|
||||
codex_error_info: Option<codex_app_server_protocol::CodexErrorInfo>,
|
||||
) -> ServerNotification {
|
||||
ServerNotification::TurnCompleted(TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: thread_id.to_string(),
|
||||
turn: Turn {
|
||||
id: turn_id.to_string(),
|
||||
|
||||
@@ -1196,6 +1196,8 @@ mod tests {
|
||||
|
||||
fn turn_completed_notification() -> ServerNotification {
|
||||
ServerNotification::TurnCompleted(codex_app_server_protocol::TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread".to_string(),
|
||||
turn: codex_app_server_protocol::Turn {
|
||||
id: "turn".to_string(),
|
||||
@@ -2096,6 +2098,8 @@ mod tests {
|
||||
&InProcessServerEvent::ServerNotification(
|
||||
codex_app_server_protocol::ServerNotification::TurnCompleted(
|
||||
codex_app_server_protocol::TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread".to_string(),
|
||||
turn: codex_app_server_protocol::Turn {
|
||||
id: "turn".to_string(),
|
||||
|
||||
@@ -4882,6 +4882,20 @@
|
||||
},
|
||||
"TurnCompletedNotification": {
|
||||
"properties": {
|
||||
"finalModel": {
|
||||
"description": "Final model used after server-side routing or fallback.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"modelSnapshot": {
|
||||
"description": "Concrete resolved model snapshot used to execute the turn.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
+14
@@ -18777,6 +18777,20 @@
|
||||
"TurnCompletedNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"finalModel": {
|
||||
"description": "Final model used after server-side routing or fallback.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"modelSnapshot": {
|
||||
"description": "Concrete resolved model snapshot used to execute the turn.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
+14
@@ -16594,6 +16594,20 @@
|
||||
"TurnCompletedNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"finalModel": {
|
||||
"description": "Final model used after server-side routing or fallback.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"modelSnapshot": {
|
||||
"description": "Concrete resolved model snapshot used to execute the turn.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
@@ -1719,6 +1719,20 @@
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"finalModel": {
|
||||
"description": "Final model used after server-side routing or fallback.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"modelSnapshot": {
|
||||
"description": "Concrete resolved model snapshot used to execute the turn.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
+9
-1
@@ -3,4 +3,12 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { Turn } from "./Turn";
|
||||
|
||||
export type TurnCompletedNotification = { threadId: string, turn: Turn, };
|
||||
export type TurnCompletedNotification = { threadId: string, turn: Turn,
|
||||
/**
|
||||
* Final model used after server-side routing or fallback.
|
||||
*/
|
||||
finalModel: string | null,
|
||||
/**
|
||||
* Concrete resolved model snapshot used to execute the turn.
|
||||
*/
|
||||
modelSnapshot: string | null, };
|
||||
|
||||
@@ -1442,6 +1442,8 @@ mod tests {
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: turn_id.to_string(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -1504,6 +1506,8 @@ mod tests {
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: turn_id.to_string(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -1582,6 +1586,8 @@ mod tests {
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-image".into(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -1933,6 +1939,8 @@ mod tests {
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -2482,6 +2490,8 @@ mod tests {
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -2524,6 +2534,8 @@ mod tests {
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-b".into(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -2580,6 +2592,8 @@ mod tests {
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -2622,6 +2636,8 @@ mod tests {
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-b".into(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -2810,6 +2826,8 @@ mod tests {
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -2832,6 +2850,8 @@ mod tests {
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -2844,6 +2864,8 @@ mod tests {
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-b".into(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -2882,6 +2904,8 @@ mod tests {
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -2944,6 +2968,8 @@ mod tests {
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-compact".into(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -3206,6 +3232,8 @@ mod tests {
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -3271,6 +3299,8 @@ mod tests {
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -3326,6 +3356,8 @@ mod tests {
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -3375,6 +3407,8 @@ mod tests {
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-a".into(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
|
||||
@@ -373,6 +373,10 @@ pub struct Usage {
|
||||
pub struct TurnCompletedNotification {
|
||||
pub thread_id: String,
|
||||
pub turn: Turn,
|
||||
/// Final model used after server-side routing or fallback.
|
||||
pub final_model: Option<String>,
|
||||
/// Concrete resolved model snapshot used to execute the turn.
|
||||
pub model_snapshot: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
|
||||
@@ -1293,7 +1293,7 @@ Because audio is intentionally separate from `ThreadItem`, clients can opt out o
|
||||
The app-server streams JSON-RPC notifications while a turn is running. Each turn emits `turn/started` when it begins running and ends with `turn/completed` (final `turn` status). Token usage events stream separately via `thread/tokenUsage/updated`. Clients subscribe to the events they care about, rendering each item incrementally as updates arrive. The per-item lifecycle is always: `item/started` → zero or more item-specific deltas → `item/completed`.
|
||||
|
||||
- `turn/started` — `{ turn }` with the turn id, empty `items`, and `status: "inProgress"`.
|
||||
- `turn/completed` — `{ turn }` where `turn.status` is `completed`, `interrupted`, or `failed`; failures carry `{ error: { message, codexErrorInfo?, additionalDetails? } }`.
|
||||
- `turn/completed` — `{ turn, finalModel, modelSnapshot }` where `turn.status` is `completed`, `interrupted`, or `failed`; execution identity fields are `null` when the Responses API does not report them, and failures carry `{ error: { message, codexErrorInfo?, additionalDetails? } }`.
|
||||
- `turn/diff/updated` — `{ threadId, turnId, diff }` represents the up-to-date snapshot of the turn-level unified diff, emitted after every FileChange item. `diff` is the latest aggregated unified diff across every file change in the turn. UIs can render this to show the full "what changed" view without stitching individual `fileChange` items.
|
||||
- `turn/plan/updated` — `{ turnId, explanation?, plan }` whenever the agent shares or changes its plan; each `plan` entry is `{ step, status }` with `status` in `pending`, `inProgress`, or `completed`.
|
||||
- `model/rerouted` — `{ threadId, turnId, fromModel, toModel, reason }` when the backend reroutes a request to a different model (for example, due to high-risk cyber safety checks).
|
||||
|
||||
@@ -1318,6 +1318,8 @@ struct TurnCompletionMetadata {
|
||||
started_at: Option<i64>,
|
||||
completed_at: Option<i64>,
|
||||
duration_ms: Option<i64>,
|
||||
final_model: Option<String>,
|
||||
model_snapshot: Option<String>,
|
||||
}
|
||||
|
||||
async fn emit_turn_completed_with_status(
|
||||
@@ -1338,6 +1340,8 @@ async fn emit_turn_completed_with_status(
|
||||
completed_at: turn_completion_metadata.completed_at,
|
||||
duration_ms: turn_completion_metadata.duration_ms,
|
||||
},
|
||||
final_model: turn_completion_metadata.final_model,
|
||||
model_snapshot: turn_completion_metadata.model_snapshot,
|
||||
};
|
||||
outgoing
|
||||
.send_server_notification(ServerNotification::TurnCompleted(notification))
|
||||
@@ -1521,6 +1525,8 @@ async fn handle_turn_complete(
|
||||
started_at: turn_summary.started_at,
|
||||
completed_at: turn_complete_event.completed_at,
|
||||
duration_ms: turn_complete_event.duration_ms,
|
||||
final_model: turn_complete_event.final_model,
|
||||
model_snapshot: turn_complete_event.model_snapshot,
|
||||
},
|
||||
outgoing,
|
||||
)
|
||||
@@ -1545,6 +1551,8 @@ async fn handle_turn_interrupted(
|
||||
started_at: turn_summary.started_at,
|
||||
completed_at: turn_aborted_event.completed_at,
|
||||
duration_ms: turn_aborted_event.duration_ms,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
},
|
||||
outgoing,
|
||||
)
|
||||
@@ -2256,6 +2264,8 @@ mod tests {
|
||||
TurnCompleteEvent {
|
||||
turn_id: turn_id.to_string(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: Some(TEST_TURN_COMPLETED_AT),
|
||||
duration_ms: Some(TEST_TURN_DURATION_MS),
|
||||
time_to_first_token_ms: None,
|
||||
@@ -3423,6 +3433,11 @@ mod tests {
|
||||
ThreadId::new(),
|
||||
);
|
||||
let thread_state = new_thread_state();
|
||||
let turn_complete = TurnCompleteEvent {
|
||||
final_model: Some("test-final-model".to_string()),
|
||||
model_snapshot: Some("test-model-snapshot".to_string()),
|
||||
..turn_complete_event(&event_turn_id)
|
||||
};
|
||||
{
|
||||
let mut state = thread_state.lock().await;
|
||||
state.track_current_turn_event(
|
||||
@@ -3437,14 +3452,14 @@ mod tests {
|
||||
);
|
||||
state.track_current_turn_event(
|
||||
&event_turn_id,
|
||||
&EventMsg::TurnComplete(turn_complete_event(&event_turn_id)),
|
||||
&EventMsg::TurnComplete(turn_complete.clone()),
|
||||
);
|
||||
}
|
||||
|
||||
handle_turn_complete(
|
||||
conversation_id,
|
||||
event_turn_id.clone(),
|
||||
turn_complete_event(&event_turn_id),
|
||||
turn_complete,
|
||||
&outgoing,
|
||||
&thread_state,
|
||||
)
|
||||
@@ -3461,6 +3476,8 @@ mod tests {
|
||||
assert_eq!(n.turn.started_at, Some(42));
|
||||
assert_eq!(n.turn.completed_at, Some(TEST_TURN_COMPLETED_AT));
|
||||
assert_eq!(n.turn.duration_ms, Some(TEST_TURN_DURATION_MS));
|
||||
assert_eq!(n.final_model.as_deref(), Some("test-final-model"));
|
||||
assert_eq!(n.model_snapshot.as_deref(), Some("test-model-snapshot"));
|
||||
}
|
||||
other => bail!("unexpected message: {other:?}"),
|
||||
}
|
||||
@@ -3511,6 +3528,8 @@ mod tests {
|
||||
assert_eq!(n.turn.error, None);
|
||||
assert_eq!(n.turn.completed_at, Some(TEST_TURN_COMPLETED_AT));
|
||||
assert_eq!(n.turn.duration_ms, Some(TEST_TURN_DURATION_MS));
|
||||
assert_eq!(n.final_model, None);
|
||||
assert_eq!(n.model_snapshot, None);
|
||||
}
|
||||
other => bail!("unexpected message: {other:?}"),
|
||||
}
|
||||
|
||||
@@ -894,6 +894,8 @@ mod tests {
|
||||
completed_at: Some(0),
|
||||
duration_ms: None,
|
||||
},
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
})
|
||||
));
|
||||
assert!(server_notification_requires_delivery(
|
||||
|
||||
@@ -160,6 +160,8 @@ async fn mark_thread_completed(thread: &CodexThread) {
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: turn.sub_id.clone(),
|
||||
last_agent_message: Some("done".to_string()),
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
|
||||
@@ -305,6 +305,8 @@ 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()),
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -1896,6 +1898,8 @@ async fn multi_agent_v2_completion_ignores_dead_direct_parent() {
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: tester_turn.sub_id.clone(),
|
||||
last_agent_message: Some("done".to_string()),
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -1983,6 +1987,8 @@ async fn multi_agent_v2_completion_queues_message_for_direct_parent() {
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: tester_turn.sub_id.clone(),
|
||||
last_agent_message: Some("done".to_string()),
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
|
||||
@@ -1111,6 +1111,8 @@ mod tests {
|
||||
msg: EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: turn_id.to_string(),
|
||||
last_agent_message: last_agent_message.map(str::to_string),
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms,
|
||||
|
||||
@@ -1980,6 +1980,8 @@ async fn guardian_reused_trunk_ignores_stale_prior_turn_completion() -> anyhow::
|
||||
"{\"risk_level\":\"high\",\"user_authorization\":\"low\",\"outcome\":\"deny\",\"rationale\":\"stale guardian rationale\"}"
|
||||
.to_string(),
|
||||
),
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: Some(1),
|
||||
|
||||
@@ -147,6 +147,8 @@ async fn record_initial_history_resumed_hydrates_previous_turn_settings_from_lif
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -218,6 +220,8 @@ async fn reconstruct_history_rollback_keeps_history_and_metadata_in_sync_for_com
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: first_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -249,6 +253,8 @@ async fn reconstruct_history_rollback_keeps_history_and_metadata_in_sync_for_com
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: rolled_back_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -322,6 +328,8 @@ async fn reconstruct_history_rollback_keeps_history_and_metadata_in_sync_for_inc
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: first_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -418,6 +426,8 @@ async fn reconstruct_history_rollback_skips_non_user_turns_for_history_and_metad
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: first_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -448,6 +458,8 @@ async fn reconstruct_history_rollback_skips_non_user_turns_for_history_and_metad
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: second_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -467,6 +479,8 @@ async fn reconstruct_history_rollback_skips_non_user_turns_for_history_and_metad
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: standalone_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -543,6 +557,8 @@ async fn reconstruct_history_rollback_counts_inter_agent_assistant_turns() {
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: first_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -564,6 +580,8 @@ async fn reconstruct_history_rollback_counts_inter_agent_assistant_turns() {
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: assistant_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -635,6 +653,8 @@ async fn reconstruct_history_rollback_clears_history_and_metadata_when_exceeding
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: only_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -688,6 +708,8 @@ async fn record_initial_history_resumed_rollback_skips_only_user_turns() {
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: user_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -707,6 +729,8 @@ async fn record_initial_history_resumed_rollback_skips_only_user_turns() {
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: standalone_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -764,6 +788,8 @@ async fn record_initial_history_resumed_rollback_drops_incomplete_user_turn_comp
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: previous_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -931,6 +957,8 @@ async fn reconstruct_history_legacy_compaction_without_replacement_history_clear
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: current_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -1005,6 +1033,8 @@ async fn record_initial_history_resumed_turn_context_after_compaction_reestablis
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: previous_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -1110,6 +1140,8 @@ async fn record_initial_history_resumed_aborted_turn_without_id_clears_active_tu
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: previous_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -1225,6 +1257,8 @@ async fn record_initial_history_resumed_unmatched_abort_preserves_active_turn_fo
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: previous_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -1262,6 +1296,8 @@ async fn record_initial_history_resumed_unmatched_abort_preserves_active_turn_fo
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: current_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -1348,6 +1384,8 @@ async fn record_initial_history_resumed_trailing_incomplete_turn_compaction_clea
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: previous_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -1509,6 +1547,8 @@ async fn record_initial_history_resumed_replaced_incomplete_compacted_turn_clear
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id: previous_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
|
||||
@@ -2595,6 +2595,8 @@ async fn record_initial_history_forked_hydrates_previous_turn_settings() {
|
||||
codex_protocol::protocol::TurnCompleteEvent {
|
||||
turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -2793,6 +2795,8 @@ async fn thread_rollback_recomputes_previous_turn_settings_and_reference_context
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: first_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -2822,6 +2826,8 @@ async fn thread_rollback_recomputes_previous_turn_settings_and_reference_context
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: rolled_back_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -2906,6 +2912,8 @@ async fn thread_rollback_restores_cleared_reference_context_item_after_compactio
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: first_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -2927,6 +2935,8 @@ 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,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -2958,6 +2968,8 @@ async fn thread_rollback_restores_cleared_reference_context_item_after_compactio
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: rolled_back_turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -3016,6 +3028,8 @@ async fn thread_rollback_persists_marker_and_replays_cumulatively() {
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -3043,6 +3057,8 @@ async fn thread_rollback_persists_marker_and_replays_cumulatively() {
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-2".to_string(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -3070,6 +3086,8 @@ async fn thread_rollback_persists_marker_and_replays_cumulatively() {
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-3".to_string(),
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
|
||||
@@ -742,6 +742,8 @@ impl Session {
|
||||
let event = EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: turn_context.sub_id.clone(),
|
||||
last_agent_message,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at,
|
||||
duration_ms,
|
||||
time_to_first_token_ms,
|
||||
|
||||
@@ -1557,6 +1557,8 @@ async fn multi_agent_v2_list_agents_returns_completed_status_without_encrypted_s
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: child_turn.sub_id.clone(),
|
||||
last_agent_message: Some("done".to_string()),
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -2008,6 +2010,8 @@ async fn multi_agent_v2_followup_task_completion_notifies_parent_on_every_turn()
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: first_turn.sub_id.clone(),
|
||||
last_agent_message: Some("first done".to_string()),
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
@@ -2037,6 +2041,8 @@ async fn multi_agent_v2_followup_task_completion_notifies_parent_on_every_turn()
|
||||
EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: second_turn.sub_id.clone(),
|
||||
last_agent_message: Some("second done".to_string()),
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
|
||||
@@ -69,6 +69,8 @@ fn resume_history(
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
|
||||
@@ -307,6 +307,8 @@ fn turn_completed_recovers_final_message_from_turn_items() {
|
||||
|
||||
let status = processor.process_server_notification(ServerNotification::TurnCompleted(
|
||||
codex_app_server_protocol::TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: Turn {
|
||||
id: "turn-1".to_string(),
|
||||
@@ -355,6 +357,8 @@ fn turn_completed_overwrites_stale_final_message_from_turn_items() {
|
||||
|
||||
let status = processor.process_server_notification(ServerNotification::TurnCompleted(
|
||||
codex_app_server_protocol::TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: Turn {
|
||||
id: "turn-1".to_string(),
|
||||
@@ -404,6 +408,8 @@ fn turn_completed_preserves_streamed_final_message_when_turn_items_are_empty() {
|
||||
|
||||
let status = processor.process_server_notification(ServerNotification::TurnCompleted(
|
||||
codex_app_server_protocol::TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: Turn {
|
||||
id: "turn-1".to_string(),
|
||||
@@ -448,6 +454,8 @@ fn turn_failed_clears_stale_final_message() {
|
||||
|
||||
let status = processor.process_server_notification(ServerNotification::TurnCompleted(
|
||||
codex_app_server_protocol::TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: Turn {
|
||||
id: "turn-1".to_string(),
|
||||
@@ -493,6 +501,8 @@ fn turn_interrupted_clears_stale_final_message() {
|
||||
|
||||
let status = processor.process_server_notification(ServerNotification::TurnCompleted(
|
||||
codex_app_server_protocol::TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: Turn {
|
||||
id: "turn-1".to_string(),
|
||||
|
||||
@@ -30,6 +30,8 @@ fn failed_turn_does_not_overwrite_output_last_message_file() {
|
||||
|
||||
let status = processor.process_server_notification(ServerNotification::TurnCompleted(
|
||||
codex_app_server_protocol::TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: codex_app_server_protocol::Turn {
|
||||
id: "turn-1".to_string(),
|
||||
|
||||
@@ -371,6 +371,8 @@ fn turn_items_for_thread_returns_matching_turn_items() {
|
||||
fn should_backfill_turn_completed_items_skips_ephemeral_threads() {
|
||||
let notification =
|
||||
ServerNotification::TurnCompleted(codex_app_server_protocol::TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: codex_app_server_protocol::Turn {
|
||||
id: "turn-1".to_string(),
|
||||
|
||||
@@ -1103,6 +1103,8 @@ fn plan_update_emits_started_then_updated_then_completed() {
|
||||
|
||||
let completed = processor.collect_thread_events(ServerNotification::TurnCompleted(
|
||||
TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: Turn {
|
||||
id: "turn-1".to_string(),
|
||||
@@ -1163,6 +1165,8 @@ fn plan_update_after_completion_starts_new_todo_list_with_new_id() {
|
||||
));
|
||||
let _ = processor.collect_thread_events(ServerNotification::TurnCompleted(
|
||||
TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: Turn {
|
||||
id: "turn-1".to_string(),
|
||||
@@ -1246,6 +1250,8 @@ fn token_usage_update_is_emitted_on_turn_completion() {
|
||||
|
||||
let completed = processor.collect_thread_events(ServerNotification::TurnCompleted(
|
||||
TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: Turn {
|
||||
id: "turn-1".to_string(),
|
||||
@@ -1281,6 +1287,8 @@ fn turn_completion_recovers_final_message_from_turn_items() {
|
||||
|
||||
let completed = processor.collect_thread_events(ServerNotification::TurnCompleted(
|
||||
TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: Turn {
|
||||
id: "turn-1".to_string(),
|
||||
@@ -1354,6 +1362,8 @@ fn turn_completion_reconciles_started_items_from_turn_items() {
|
||||
|
||||
let completed = processor.collect_thread_events(ServerNotification::TurnCompleted(
|
||||
TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: Turn {
|
||||
id: "turn-1".to_string(),
|
||||
@@ -1422,6 +1432,8 @@ fn turn_completion_overwrites_stale_final_message_from_turn_items() {
|
||||
|
||||
let completed = processor.collect_thread_events(ServerNotification::TurnCompleted(
|
||||
TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: Turn {
|
||||
id: "turn-1".to_string(),
|
||||
@@ -1472,6 +1484,8 @@ fn turn_completion_preserves_streamed_final_message_when_turn_items_are_empty()
|
||||
|
||||
let completed = processor.collect_thread_events(ServerNotification::TurnCompleted(
|
||||
TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: Turn {
|
||||
id: "turn-1".to_string(),
|
||||
@@ -1521,6 +1535,8 @@ fn failed_turn_clears_stale_final_message() {
|
||||
|
||||
let collected = processor.collect_thread_events(ServerNotification::TurnCompleted(
|
||||
TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: Turn {
|
||||
id: "turn-1".to_string(),
|
||||
@@ -1549,6 +1565,8 @@ fn turn_completion_falls_back_to_final_plan_text() {
|
||||
|
||||
let completed = processor.collect_thread_events(ServerNotification::TurnCompleted(
|
||||
TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: Turn {
|
||||
id: "turn-1".to_string(),
|
||||
@@ -1604,6 +1622,8 @@ fn turn_failure_prefers_structured_error_message() {
|
||||
|
||||
let failed = processor.collect_thread_events(ServerNotification::TurnCompleted(
|
||||
TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: Turn {
|
||||
id: "turn-1".to_string(),
|
||||
|
||||
@@ -167,6 +167,8 @@ fn turn_complete_item(turn_id: String, completed_at: Option<i64>) -> RolloutItem
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id,
|
||||
last_agent_message: None,
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
completed_at,
|
||||
duration_ms: None,
|
||||
time_to_first_token_ms: None,
|
||||
|
||||
@@ -1876,6 +1876,16 @@ pub struct ContextCompactedEvent;
|
||||
pub struct TurnCompleteEvent {
|
||||
pub turn_id: String,
|
||||
pub last_agent_message: Option<String>,
|
||||
/// Final model used by the terminal successful sampling request, after routing or fallback.
|
||||
#[serde(default, skip_serializing, skip_deserializing)]
|
||||
#[schemars(skip)]
|
||||
#[ts(skip)]
|
||||
pub final_model: Option<String>,
|
||||
/// Concrete model snapshot used by the terminal successful sampling request.
|
||||
#[serde(default, skip_serializing, skip_deserializing)]
|
||||
#[schemars(skip)]
|
||||
#[ts(skip)]
|
||||
pub model_snapshot: Option<String>,
|
||||
/// Unix timestamp (in seconds) when the turn completed.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(type = "number | null", optional)]
|
||||
@@ -5307,6 +5317,32 @@ mod tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn turn_complete_execution_identity_is_not_serialized() -> Result<()> {
|
||||
let event = EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
last_agent_message: Some("done".to_string()),
|
||||
final_model: Some("test-final-model".to_string()),
|
||||
model_snapshot: Some("test-model-snapshot".to_string()),
|
||||
completed_at: Some(1_717_171_717),
|
||||
duration_ms: Some(1_234),
|
||||
time_to_first_token_ms: Some(321),
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
serde_json::to_value(event)?,
|
||||
json!({
|
||||
"type": "task_complete",
|
||||
"turn_id": "turn-1",
|
||||
"last_agent_message": "done",
|
||||
"completed_at": 1_717_171_717,
|
||||
"duration_ms": 1_234,
|
||||
"time_to_first_token_ms": 321,
|
||||
})
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_legacy_session_configured_event_uses_sandbox_policy() -> Result<()> {
|
||||
let cwd = test_path_buf("/home/user/project");
|
||||
|
||||
@@ -664,6 +664,8 @@ mod tests {
|
||||
|
||||
fn turn_completed(turn_id: &str) -> ServerNotification {
|
||||
ServerNotification::TurnCompleted(TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: Turn {
|
||||
id: turn_id.to_string(),
|
||||
|
||||
@@ -4403,6 +4403,8 @@ fn turn_completed_notification(
|
||||
duration_ms: Some(1),
|
||||
..test_turn(turn_id, status, Vec::new())
|
||||
},
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -416,6 +416,8 @@ mod tests {
|
||||
duration_ms: Some(1),
|
||||
..test_turn(turn_id, status, Vec::new())
|
||||
},
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@ impl ChatWidget {
|
||||
) {
|
||||
self.handle_turn_completed_notification(
|
||||
TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: self.thread_id.map(|id| id.to_string()).unwrap_or_default(),
|
||||
turn: Turn {
|
||||
id: turn_id,
|
||||
|
||||
@@ -346,6 +346,8 @@ async fn live_app_server_turn_completed_clears_working_status_after_answer_item(
|
||||
|
||||
chat.handle_server_notification(
|
||||
ServerNotification::TurnCompleted(TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: AppServerTurn {
|
||||
id: "turn-1".to_string(),
|
||||
@@ -766,6 +768,8 @@ async fn live_app_server_failed_turn_does_not_duplicate_error_history() {
|
||||
|
||||
chat.handle_server_notification(
|
||||
ServerNotification::TurnCompleted(TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: AppServerTurn {
|
||||
id: "turn-1".to_string(),
|
||||
|
||||
@@ -996,6 +996,8 @@ pub(super) fn handle_turn_completed(
|
||||
) {
|
||||
chat.handle_server_notification(
|
||||
ServerNotification::TurnCompleted(TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: chat.thread_id.map(|id| id.to_string()).unwrap_or_default(),
|
||||
turn: app_server_turn(
|
||||
turn_id,
|
||||
@@ -1011,6 +1013,8 @@ pub(super) fn handle_turn_completed(
|
||||
pub(super) fn handle_turn_interrupted(chat: &mut ChatWidget, turn_id: &str) {
|
||||
chat.handle_server_notification(
|
||||
ServerNotification::TurnCompleted(TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: chat.thread_id.map(|id| id.to_string()).unwrap_or_default(),
|
||||
turn: app_server_turn(
|
||||
turn_id,
|
||||
|
||||
@@ -1172,6 +1172,8 @@ async fn submit_user_message_queues_while_compaction_turn_is_running() {
|
||||
|
||||
chat.handle_server_notification(
|
||||
ServerNotification::TurnCompleted(TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: thread_id.to_string(),
|
||||
turn: AppServerTurn {
|
||||
id: "turn-1".to_string(),
|
||||
|
||||
@@ -1271,6 +1271,8 @@ async fn interrupted_turn_after_goal_budget_limited_uses_budget_message_snapshot
|
||||
chat.handle_server_notification(
|
||||
codex_app_server_protocol::ServerNotification::TurnCompleted(
|
||||
codex_app_server_protocol::TurnCompletedNotification {
|
||||
final_model: None,
|
||||
model_snapshot: None,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn: codex_app_server_protocol::Turn {
|
||||
id: "turn-1".to_string(),
|
||||
|
||||
Reference in New Issue
Block a user