| 380 | } |
| 381 | |
| 382 | fn restore_turn_payload_stats(turns: &[DialogTurnData]) -> RestoreTurnPayloadStats { |
| 383 | let mut stats = RestoreTurnPayloadStats::default(); |
| 384 | for turn in turns { |
| 385 | for (round_index, round) in turn.model_rounds.iter().enumerate() { |
| 386 | for (tool_index, tool) in round.tool_items.iter().enumerate() { |
| 387 | let Some(result) = tool.tool_result.as_ref() else { |
| 388 | continue; |
| 389 | }; |
| 390 | stats.tool_result_count += 1; |
| 391 | let assistant_chars = result |
| 392 | .result_for_assistant |
| 393 | .as_deref() |
| 394 | .map(|text| text.chars().count()) |
| 395 | .unwrap_or(0); |
| 396 | stats.result_for_assistant_chars += assistant_chars; |
| 397 | let mut json_stats = JsonStringStats::default(); |
| 398 | collect_json_string_stats( |
| 399 | &result.result, |
| 400 | &format!( |
| 401 | "turn[{}].round[{}].tool[{}].{}", |
| 402 | turn.turn_index, round_index, tool_index, tool.tool_name |
| 403 | ), |
| 404 | &mut json_stats, |
| 405 | ); |
| 406 | stats.raw_result_string_chars += json_stats.total_chars; |
| 407 | if json_stats.largest_chars > stats.largest_raw_result_chars { |
| 408 | stats.largest_raw_result_chars = json_stats.largest_chars; |
| 409 | stats.largest_raw_result_path = json_stats.largest_path.clone(); |
| 410 | } |
| 411 | push_top_raw_result( |
| 412 | &mut stats, |
| 413 | RestoreToolOutputStats { |
| 414 | tool_name: tool.tool_name.clone(), |
| 415 | path: json_stats.largest_path, |
| 416 | raw_result_string_chars: json_stats.total_chars, |
| 417 | result_for_assistant_chars: assistant_chars, |
| 418 | }, |
| 419 | ); |
| 420 | } |
| 421 | } |
| 422 | } |
| 423 | stats |
| 424 | } |
| 425 | |
| 426 | fn truncate_string_for_session_view(text: &str, remaining_budget: &mut usize) -> Option<String> { |
| 427 | let char_count = text.chars().count(); |