Download codex-rs/app-server/src/request_processors/thread_delete.rs from SaylorTwift/codex: direct link, hf CLI and curl.
- Browser
- Download file 5.3 kB
-
https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/app-server/src/request_processors/thread_delete.rs
- Command line
-
hf download hf://SaylorTwift/codex/codex-rs/app-server/src/request_processors/thread_delete.rs
-
curl -L -o thread_delete.rs https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/app-server/src/request_processors/thread_delete.rs
5.3 kB
| //! `thread/delete` request handling. | |
| use super::thread_processor::unsupported_thread_store_operation; | |
| use super::*; | |
| impl ThreadRequestProcessor { | |
| pub(crate) async fn thread_delete( | |
| &self, | |
| request_id: ConnectionRequestId, | |
| params: ThreadDeleteParams, | |
| ) -> Result<Option<ClientResponsePayload>, JSONRPCErrorError> { | |
| let mut deleted_thread_ids = Vec::new(); | |
| let result = { | |
| let _thread_list_state_permit = self.acquire_thread_list_state_permit().await?; | |
| self.thread_delete_response(params, &mut deleted_thread_ids) | |
| .await | |
| }; | |
| match result { | |
| Ok(response) => { | |
| self.outgoing | |
| .send_response(request_id.clone(), response) | |
| .await; | |
| self.send_thread_deleted_notifications(deleted_thread_ids) | |
| .await; | |
| Ok(None) | |
| } | |
| Err(error) => Err(error), | |
| } | |
| } | |
| async fn thread_delete_response( | |
| &self, | |
| params: ThreadDeleteParams, | |
| deleted_thread_ids: &mut Vec<String>, | |
| ) -> Result<ThreadDeleteResponse, JSONRPCErrorError> { | |
| let thread_id = ThreadId::from_string(¶ms.thread_id) | |
| .map_err(|err| invalid_request(format!("invalid thread id: {err}")))?; | |
| let thread_ids = self.state_db_spawn_subtree_thread_ids(thread_id).await?; | |
| self.validate_root_thread_delete(thread_id, thread_ids.len() > 1) | |
| .await?; | |
| for thread_id_to_delete in thread_ids.iter().copied() { | |
| self.prepare_thread_for_delete(thread_id_to_delete).await?; | |
| } | |
| let mut delete_order: Vec<_> = thread_ids.iter().skip(1).rev().copied().collect(); | |
| delete_order.push(thread_id); | |
| self.thread_store | |
| .delete_threads(StoreDeleteThreadsParams { | |
| thread_ids: delete_order.clone(), | |
| }) | |
| .await | |
| .map_err(thread_store_delete_error)?; | |
| deleted_thread_ids.extend( | |
| delete_order | |
| .into_iter() | |
| .map(|thread_id| thread_id.to_string()), | |
| ); | |
| Ok(ThreadDeleteResponse {}) | |
| } | |
| async fn send_thread_deleted_notifications(&self, deleted_thread_ids: Vec<String>) { | |
| for thread_id in deleted_thread_ids { | |
| self.outgoing | |
| .send_server_notification(ServerNotification::ThreadDeleted( | |
| ThreadDeletedNotification { thread_id }, | |
| )) | |
| .await; | |
| } | |
| } | |
| async fn validate_root_thread_delete( | |
| &self, | |
| thread_id: ThreadId, | |
| has_descendants: bool, | |
| ) -> Result<(), JSONRPCErrorError> { | |
| if let Ok(thread) = self.thread_manager.get_thread(thread_id).await { | |
| if !thread.config_snapshot().await.ephemeral { | |
| return Ok(()); | |
| } | |
| return Err(invalid_request(format!( | |
| "thread is not persisted and cannot be deleted: {thread_id}" | |
| ))); | |
| } | |
| match self | |
| .thread_store | |
| .read_thread(StoreReadThreadParams { | |
| thread_id, | |
| include_archived: true, | |
| include_history: false, | |
| }) | |
| .await | |
| { | |
| Ok(_) => Ok(()), | |
| Err(ThreadStoreError::ThreadNotFound { .. }) => { | |
| if has_descendants { | |
| return Ok(()); | |
| } | |
| let Some(state_db) = self.state_db.as_ref() else { | |
| return Err(thread_store_delete_error( | |
| ThreadStoreError::ThreadNotFound { thread_id }, | |
| )); | |
| }; | |
| if state_db | |
| .get_thread(thread_id) | |
| .await | |
| .map_err(|err| { | |
| internal_error(format!( | |
| "failed to read app-server state for {thread_id}: {err}" | |
| )) | |
| })? | |
| .is_some() | |
| { | |
| Ok(()) | |
| } else { | |
| Err(thread_store_delete_error( | |
| ThreadStoreError::ThreadNotFound { thread_id }, | |
| )) | |
| } | |
| } | |
| Err(err) => Err(thread_store_delete_error(err)), | |
| } | |
| } | |
| async fn prepare_thread_for_delete( | |
| &self, | |
| thread_id: ThreadId, | |
| ) -> Result<(), JSONRPCErrorError> { | |
| self.prepare_thread_for_removal(thread_id, "delete").await?; | |
| if let Some(log_db) = self.log_db.as_ref() { | |
| log_db.flush().await; | |
| } | |
| Ok(()) | |
| } | |
| } | |
| fn thread_store_delete_error(err: ThreadStoreError) -> JSONRPCErrorError { | |
| match err { | |
| ThreadStoreError::ThreadNotFound { thread_id } => { | |
| invalid_request(format!("thread not found: {thread_id}")) | |
| } | |
| ThreadStoreError::InvalidRequest { message } | ThreadStoreError::Conflict { message } => { | |
| invalid_request(message) | |
| } | |
| ThreadStoreError::Unsupported { operation } => { | |
| unsupported_thread_store_operation(operation) | |
| } | |
| err => internal_error(format!("failed to delete thread: {err}")), | |
| } | |
| } | |