(
State(state): State<Arc<ServerState>>,
Path((session_id, msg_id, part_id)): Path<(String, String, String)>,
Json(req): Json<UpdatePartRequest>,
)
| 1889 | } |
| 1890 | |
| 1891 | async fn update_part( |
| 1892 | State(state): State<Arc<ServerState>>, |
| 1893 | Path((session_id, msg_id, part_id)): Path<(String, String, String)>, |
| 1894 | Json(req): Json<UpdatePartRequest>, |
| 1895 | ) -> Result<Json<serde_json::Value>> { |
| 1896 | let mut sessions = state.sessions.lock().await; |
| 1897 | let session = sessions |
| 1898 | .get_mut(&session_id) |
| 1899 | .ok_or_else(|| ApiError::SessionNotFound(session_id.clone()))?; |
| 1900 | let message = session |
| 1901 | .get_message_mut(&msg_id) |
| 1902 | .ok_or_else(|| ApiError::NotFound(format!("Message not found: {}", msg_id)))?; |
| 1903 | |
| 1904 | let mut part: opencode_session::MessagePart = serde_json::from_value(req.part) |
| 1905 | .map_err(|e| ApiError::BadRequest(format!("Invalid part payload: {}", e)))?; |
| 1906 | if part.id != part_id { |
| 1907 | return Err(ApiError::BadRequest(format!( |
| 1908 | "Part id mismatch: body has {}, path has {}", |
| 1909 | part.id, part_id |
| 1910 | ))); |
| 1911 | } |
| 1912 | part.message_id = Some(msg_id.clone()); |
| 1913 | |
| 1914 | let updated_part = { |
| 1915 | let target = message |
| 1916 | .parts |
| 1917 | .iter_mut() |
| 1918 | .find(|existing| existing.id == part_id) |
| 1919 | .ok_or_else(|| ApiError::NotFound(format!("Part not found: {}", part_id)))?; |
| 1920 | *target = part.clone(); |
| 1921 | target.clone() |
| 1922 | }; |
| 1923 | session.touch(); |
| 1924 | drop(sessions); |
| 1925 | persist_sessions_if_enabled(&state).await; |
| 1926 | |
| 1927 | Ok(Json(serde_json::json!({ |
| 1928 | "updated": true, |
| 1929 | "part": updated_part, |
| 1930 | }))) |
| 1931 | } |
| 1932 | |
| 1933 | #[derive(Debug, Deserialize)] |
| 1934 | pub struct ExecuteShellRequest { |
nothing calls this directly
no test coverage detected