Stop emitting item/fileChange/outputDelta output delta notifications (#20471)

## Why

`item/fileChange/outputDelta` text output was only the tool's summary or
error text and not used by client surfaces.

We keep `item/fileChange/outputDelta` in the app-server protocol as a
deprecated compatibility entry, but the server no longer emits it.

## What changed

- stop the `apply_patch` runtime from emitting `ExecCommandOutputDelta`
events
- simplify `item_event_to_server_notification` so command output deltas
always map to `item/commandExecution/outputDelta`
- remove the app-server bookkeeping that tried to detect whether an
output delta belonged to a file change
- mark `item/fileChange/outputDelta` as a deprecated legacy protocol
entry in the v2 types, schema, and README
- simplify the file-change approval tests so they only wait for
completion instead of expecting output-delta notifications

## Testing

- `cargo test -p codex-app-server-protocol`
- `cargo test -p codex-thread-manager-sample`
- `cargo test -p codex-app-server-protocol
protocol::event_mapping::tests::exec_command_output_delta_maps_to_command_execution_output_delta
-- --exact`
- `cargo test -p codex-app-server
turn_start_file_change_approval_accept_for_session_persists_v2 --
--exact` *(failed before the test assertions because the wiremock
`/responses` mock received 0 requests in setup)*
This commit is contained in:
pakrym-oai
2026-04-30 11:42:07 -07:00
committed by GitHub
Unverified
parent f2bc2f26a9
commit b52083146c
13 changed files with 59 additions and 96 deletions
@@ -887,7 +887,6 @@ pub(crate) async fn apply_bespoke_event_handling(
msg,
&conversation_id.to_string(),
&event_turn_id,
/*is_file_change_output*/ false,
);
outgoing.send_server_notification(notification).await;
}
@@ -905,7 +904,6 @@ pub(crate) async fn apply_bespoke_event_handling(
EventMsg::CollabCloseEnd(end_event),
&conversation_id.to_string(),
&event_turn_id,
/*is_file_change_output*/ false,
);
outgoing.send_server_notification(notification).await;
}
@@ -1041,7 +1039,6 @@ pub(crate) async fn apply_bespoke_event_handling(
msg,
&conversation_id.to_string(),
&event_turn_id,
/*is_file_change_output*/ false,
);
outgoing.send_server_notification(notification).await;
}
@@ -1124,7 +1121,6 @@ pub(crate) async fn apply_bespoke_event_handling(
EventMsg::PatchApplyBegin(patch_begin_event),
&conversation_id.to_string(),
&event_turn_id,
/*is_file_change_output*/ false,
);
outgoing.send_server_notification(notification).await;
}
@@ -1166,28 +1162,15 @@ pub(crate) async fn apply_bespoke_event_handling(
EventMsg::ExecCommandBegin(exec_command_begin_event),
&conversation_id.to_string(),
&event_turn_id,
/*is_file_change_output*/ false,
);
outgoing.send_server_notification(notification).await;
}
}
EventMsg::ExecCommandOutputDelta(exec_command_output_delta_event) => {
let item_id = exec_command_output_delta_event.call_id.clone();
// The underlying EventMsg::ExecCommandOutputDelta is used for shell, unified_exec,
// and apply_patch tool calls. We represent apply_patch with the FileChange item, and
// everything else with the CommandExecution item.
//
// We need to detect which item type it is so we can emit the right notification.
// We already have state tracking FileChange items on item/started, so let's use that.
let is_file_change = {
let state = thread_state.lock().await;
state.turn_summary.file_change_started.contains(&item_id)
};
let notification = item_event_to_server_notification(
EventMsg::ExecCommandOutputDelta(exec_command_output_delta_event),
&conversation_id.to_string(),
&event_turn_id,
is_file_change,
);
outgoing.send_server_notification(notification).await;
}
@@ -1213,7 +1196,6 @@ pub(crate) async fn apply_bespoke_event_handling(
EventMsg::ExecCommandEnd(exec_command_end_event),
&conversation_id.to_string(),
&event_turn_id,
/*is_file_change_output*/ false,
);
outgoing.send_server_notification(notification).await;
}