Strip transcript and reasoning from a change for privacy. Replaces the unhashed turn data with a minimal stub that has `redacted: true`. The change hash is NOT affected. Returns `true` if data was stripped, `false` if there was nothing to strip.
(change: &mut atomic_core::change::Change)
| 150 | /// |
| 151 | /// Returns `true` if data was stripped, `false` if there was nothing to strip. |
| 152 | pub fn strip_unhashed(change: &mut atomic_core::change::Change) -> bool { |
| 153 | let Some(unhashed) = change.unhashed.as_mut() else { |
| 154 | return false; |
| 155 | }; |
| 156 | let Some(obj) = unhashed.as_object_mut() else { |
| 157 | return false; |
| 158 | }; |
| 159 | |
| 160 | if !obj.contains_key(UNHASHED_KEY) { |
| 161 | return false; |
| 162 | } |
| 163 | |
| 164 | // Extract just the session_id and turn_number for the stub |
| 165 | let stub = if let Some(existing) = obj.get(UNHASHED_KEY) { |
| 166 | let session_id = existing |
| 167 | .get("session_id") |
| 168 | .and_then(|v| v.as_str()) |
| 169 | .unwrap_or("") |
| 170 | .to_string(); |
| 171 | let turn_number = existing |
| 172 | .get("turn_number") |
| 173 | .and_then(|v| v.as_u64()) |
| 174 | .unwrap_or(0) as u32; |
| 175 | |
| 176 | serde_json::json!({ |
| 177 | "session_id": session_id, |
| 178 | "turn_number": turn_number, |
| 179 | "transcript_format": "redacted", |
| 180 | "condensed_transcript": [], |
| 181 | "condensed_text": "", |
| 182 | "prompts": [], |
| 183 | "tools_used": [], |
| 184 | "reasoning": null, |
| 185 | "redacted": true |
| 186 | }) |
| 187 | } else { |
| 188 | serde_json::json!({ "redacted": true }) |
| 189 | }; |
| 190 | |
| 191 | obj.insert(UNHASHED_KEY.to_string(), stub); |
| 192 | true |
| 193 | } |
| 194 | |
| 195 | /// Check if a change has unhashed agent turn data. |
| 196 | pub fn has_unhashed(change: &atomic_core::change::Change) -> bool { |