Skip to content

Commit ba3c1fe

Browse files
committed
fix(tui): handle legacy exec approvals compatibly
Treat legacy `ExecCommandApproval` requests as a compatibility path regardless of transport so older request shapes continue to surface in the existing exec approval UI instead of failing on session type. Restore `active_thread_rx` before reinserting retained thread events and use non-blocking refill logic so resolved-approval cleanup cannot deadlock while the receiver is detached.
1 parent bbbaa81 commit ba3c1fe

2 files changed

Lines changed: 30 additions & 10 deletions

File tree

codex-rs/tui_app_server/src/app.rs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1660,13 +1660,35 @@ impl App {
16601660
return;
16611661
}
16621662

1663-
for event in retained_events {
1664-
if sender.send(event).await.is_err() {
1665-
self.clear_active_thread().await;
1666-
return;
1663+
self.active_thread_rx = Some(rx);
1664+
1665+
if retained_events.is_empty() {
1666+
return;
1667+
}
1668+
1669+
let mut pending_events = retained_events.into_iter();
1670+
while let Some(event) = pending_events.next() {
1671+
match sender.try_send(event) {
1672+
Ok(()) => {}
1673+
Err(TrySendError::Full(event)) => {
1674+
let remaining_events: Vec<_> =
1675+
std::iter::once(event).chain(pending_events).collect();
1676+
tokio::spawn(async move {
1677+
for event in remaining_events {
1678+
if let Err(err) = sender.send(event).await {
1679+
tracing::warn!("thread {thread_id} event channel closed: {err}");
1680+
break;
1681+
}
1682+
}
1683+
});
1684+
return;
1685+
}
1686+
Err(TrySendError::Closed(_)) => {
1687+
self.clear_active_thread().await;
1688+
return;
1689+
}
16671690
}
16681691
}
1669-
self.active_thread_rx = Some(rx);
16701692
}
16711693

16721694
async fn active_turn_id_for_thread(&self, thread_id: ThreadId) -> Option<String> {

codex-rs/tui_app_server/src/app/app_server_adapter.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ impl App {
165165
request: ServerRequest,
166166
) {
167167
if self
168-
.try_handle_legacy_remote_exec_approval_request(app_server_client, &request)
168+
.try_handle_legacy_exec_approval_request(app_server_client, &request)
169169
.await
170170
{
171171
return;
@@ -211,14 +211,12 @@ impl App {
211211
}
212212
}
213213

214-
async fn try_handle_legacy_remote_exec_approval_request(
214+
async fn try_handle_legacy_exec_approval_request(
215215
&mut self,
216216
app_server_client: &AppServerSession,
217217
request: &ServerRequest,
218218
) -> bool {
219-
if !app_server_client.is_remote()
220-
|| !matches!(request, ServerRequest::ExecCommandApproval { .. })
221-
{
219+
if !matches!(request, ServerRequest::ExecCommandApproval { .. }) {
222220
return false;
223221
}
224222

0 commit comments

Comments
 (0)