(root: &Path)
| 233 | } |
| 234 | |
| 235 | fn collect_task_api_paths(root: &Path) -> Vec<PathBuf> { |
| 236 | let Ok(entries) = std::fs::read_dir(root) else { |
| 237 | return Vec::new(); |
| 238 | }; |
| 239 | let mut task_dirs: Vec<(u64, PathBuf)> = entries |
| 240 | .flatten() |
| 241 | .filter_map(|entry| { |
| 242 | let path = entry.path(); |
| 243 | if !path.is_dir() { |
| 244 | return None; |
| 245 | } |
| 246 | let mtime = entry |
| 247 | .metadata() |
| 248 | .ok() |
| 249 | .and_then(|meta| meta.modified().ok()) |
| 250 | .and_then(|time| time.duration_since(UNIX_EPOCH).ok()) |
| 251 | .map_or(0, |duration| duration.as_secs()); |
| 252 | Some((mtime, path)) |
| 253 | }) |
| 254 | .collect(); |
| 255 | task_dirs.sort_by_key(|b| std::cmp::Reverse(b.0)); |
| 256 | task_dirs.truncate(MAX_TASK_DIRS_PER_ROOT); |
| 257 | |
| 258 | let mut out = Vec::new(); |
| 259 | for (_, task_dir) in task_dirs { |
| 260 | for name in ["api_conversation_history.json", "api_messages.json"] { |
| 261 | let path = task_dir.join(name); |
| 262 | if path.is_file() { |
| 263 | out.push(path); |
| 264 | } |
| 265 | } |
| 266 | } |
| 267 | out |
| 268 | } |
| 269 | |
| 270 | fn read_task_metadata(task_dir: &Path) -> Option<Value> { |
| 271 | for name in ["task_metadata.json", "history_item.json", "history.json"] { |
no test coverage detected