Repository: openai/codex
File: codex-rs/core/src/codex.rs (Rust)

Code before:
                            cwd: turn_context.cwd.display().to_string(),
                            input_messages: turn_input_messages,
                            last_assistant_message: last_agent_message.clone(),
                        });
                    break;
                }
                continue;
            }
            Err(CodexErr::TurnAborted) => {
                // Aborted turn is reported via a different event.
                break;
            }
            Err(CodexErr::InvalidImageRequest()) => {
                let mut state = sess.state.lock().await;
                error_or_panic(
                    "Invalid image detected, replacing it in the last turn to prevent poisoning",
                );
                state.history.replace_last_turn_images("Invalid image");
            }
            Err(e) => {
                info!("Turn error: {e:#}");
                let event = EventMsg::Error(e.to_error_event(None));
                sess.send_event(&turn_context, event).await;
                // let the user continue the conversation
                break;
            }
        }
    }

    last_agent_message
}

async fn run_auto_compact(sess: &Arc<Session>, turn_context: &Arc<TurnContext>) {
    if should_use_remote_compact_task(sess.as_ref(), &turn_context.client.get_provider()) {
        run_inline_remote_auto_compact_task(Arc::clone(sess), Arc::clone(turn_context)).await;
    } else {
        run_inline_auto_compact_task(Arc::clone(sess), Arc::clone(turn_context)).await;
    }
}

#[instrument(level = "trace",
    skip_all,
    fields(
        turn_id = %turn_context.sub_id,
        model = %turn_context.client.get_model(),
        cwd = %turn_context.cwd.display()
    )
)]
async fn run_model_turn(
    sess: Arc<Session>,
    turn_context: Arc<TurnContext>,

Review comment (suggestion):
So for app server, we are still sending a generic `EventMsg::Error` with a specific message and I think we can parse that out. 

Not sure if we are at a point for us to develop specific error types at this point just for app sever consumers. 

Code after:
                            cwd: turn_context.cwd.display().to_string(),
                            input_messages: turn_input_messages,
                            last_assistant_message: last_agent_message.clone(),
                        });
                    break;
                }
                continue;
            }
            Err(CodexErr::TurnAborted) => {
                // Aborted turn is reported via a different event.
                break;
            }
            Err(CodexErr::InvalidImageRequest()) => {
                let mut state = sess.state.lock().await;
                error_or_panic(
                    "Invalid image detected; sanitizing tool output to prevent poisoning",
                );
                if state.history.replace_last_turn_images("Invalid image") {
                    continue;
                }
                let event = EventMsg::Error(ErrorEvent {
                    message: "Invalid image in your last message. Please remove it and try again."
                        .to_string(),
                    codex_error_info: Some(CodexErrorInfo::BadRequest),
                });
                sess.send_event(&turn_context, event).await;
                break;
            }
            Err(e) => {
                info!("Turn error: {e:#}");
                let event = EventMsg::Error(e.to_error_event(None));
                sess.send_event(&turn_context, event).await;
                // let the user continue the conversation
                break;
            }
        }
    }

    last_agent_message
}

async fn run_auto_compact(sess: &Arc<Session>, turn_context: &Arc<TurnContext>) {
    if should_use_remote_compact_task(sess.as_ref(), &turn_context.client.get_provider()) {
        run_inline_remote_auto_compact_task(Arc::clone(sess), Arc::clone(turn_context)).await;
    } else {
        run_inline_auto_compact_task(Arc::clone(sess), Arc::clone(turn_context)).await;
    }
}

#[instrument(level = "trace",
    skip_all,