From 0f220672420dc97f06ba1eb90bb6609246bfefa4 Mon Sep 17 00:00:00 2001 From: Anton Panasenko Date: Fri, 31 Oct 2025 15:28:04 -0700 Subject: [PATCH] [codex][app-server] improve error response for client requests (#6050) --- codex-rs/app-server/src/message_processor.rs | 119 +++++++++++-------- 1 file changed, 67 insertions(+), 52 deletions(-) diff --git a/codex-rs/app-server/src/message_processor.rs b/codex-rs/app-server/src/message_processor.rs index 7693cc2f..a97b037b 100644 --- a/codex-rs/app-server/src/message_processor.rs +++ b/codex-rs/app-server/src/message_processor.rs @@ -64,64 +64,79 @@ impl MessageProcessor { pub(crate) async fn process_request(&mut self, request: JSONRPCRequest) { let request_id = request.id.clone(); - if let Ok(request_json) = serde_json::to_value(request) - && let Ok(codex_request) = serde_json::from_value::(request_json) - { - match codex_request { - // Handle Initialize internally so CodexMessageProcessor does not have to concern - // itself with the `initialized` bool. - ClientRequest::Initialize { request_id, params } => { - if self.initialized { - let error = JSONRPCErrorError { - code: INVALID_REQUEST_ERROR_CODE, - message: "Already initialized".to_string(), - data: None, - }; - self.outgoing.send_error(request_id, error).await; - return; - } else { - let ClientInfo { - name, - title: _title, - version, - } = params.client_info; - let user_agent_suffix = format!("{name}; {version}"); - if let Ok(mut suffix) = USER_AGENT_SUFFIX.lock() { - *suffix = Some(user_agent_suffix); - } + let request_json = match serde_json::to_value(&request) { + Ok(request_json) => request_json, + Err(err) => { + let error = JSONRPCErrorError { + code: INVALID_REQUEST_ERROR_CODE, + message: format!("Invalid request: {err}"), + data: None, + }; + self.outgoing.send_error(request_id, error).await; + return; + } + }; - let user_agent = get_codex_user_agent(); - let response = InitializeResponse { user_agent }; - self.outgoing.send_response(request_id, response).await; + let codex_request = match serde_json::from_value::(request_json) { + Ok(codex_request) => codex_request, + Err(err) => { + let error = JSONRPCErrorError { + code: INVALID_REQUEST_ERROR_CODE, + message: format!("Invalid request: {err}"), + data: None, + }; + self.outgoing.send_error(request_id, error).await; + return; + } + }; - self.initialized = true; - return; - } - } - _ => { - if !self.initialized { - let error = JSONRPCErrorError { - code: INVALID_REQUEST_ERROR_CODE, - message: "Not initialized".to_string(), - data: None, - }; - self.outgoing.send_error(request_id, error).await; - return; + match codex_request { + // Handle Initialize internally so CodexMessageProcessor does not have to concern + // itself with the `initialized` bool. + ClientRequest::Initialize { request_id, params } => { + if self.initialized { + let error = JSONRPCErrorError { + code: INVALID_REQUEST_ERROR_CODE, + message: "Already initialized".to_string(), + data: None, + }; + self.outgoing.send_error(request_id, error).await; + return; + } else { + let ClientInfo { + name, + title: _title, + version, + } = params.client_info; + let user_agent_suffix = format!("{name}; {version}"); + if let Ok(mut suffix) = USER_AGENT_SUFFIX.lock() { + *suffix = Some(user_agent_suffix); } + + let user_agent = get_codex_user_agent(); + let response = InitializeResponse { user_agent }; + self.outgoing.send_response(request_id, response).await; + + self.initialized = true; + return; + } + } + _ => { + if !self.initialized { + let error = JSONRPCErrorError { + code: INVALID_REQUEST_ERROR_CODE, + message: "Not initialized".to_string(), + data: None, + }; + self.outgoing.send_error(request_id, error).await; + return; } } - - self.codex_message_processor - .process_request(codex_request) - .await; - } else { - let error = JSONRPCErrorError { - code: INVALID_REQUEST_ERROR_CODE, - message: "Invalid request".to_string(), - data: None, - }; - self.outgoing.send_error(request_id, error).await; } + + self.codex_message_processor + .process_request(codex_request) + .await; } pub(crate) async fn process_notification(&self, notification: JSONRPCNotification) {