| 66 | } |
| 67 | |
| 68 | fn compact_task_output(output: &str) -> (String, bool) { |
| 69 | if output.len() <= TASK_OUTPUT_CONTEXT_LIMIT { |
| 70 | return (output.to_string(), false); |
| 71 | } |
| 72 | |
| 73 | let head = crate::text::truncate_utf8(output, TASK_OUTPUT_CONTEXT_HEAD); |
| 74 | let tail_start = output |
| 75 | .char_indices() |
| 76 | .find_map(|(idx, _)| { |
| 77 | if output.len().saturating_sub(idx) <= TASK_OUTPUT_CONTEXT_TAIL { |
| 78 | Some(idx) |
| 79 | } else { |
| 80 | None |
| 81 | } |
| 82 | }) |
| 83 | .unwrap_or(output.len()); |
| 84 | let tail = &output[tail_start..]; |
| 85 | |
| 86 | ( |
| 87 | format!( |
| 88 | "{}\n\n[{} bytes omitted from delegated task output]\n\n{}", |
| 89 | head, |
| 90 | output.len().saturating_sub(head.len() + tail.len()), |
| 91 | tail |
| 92 | ), |
| 93 | true, |
| 94 | ) |
| 95 | } |
| 96 | |
| 97 | /// Translate selected child-loop events into a `SubagentProgress` milestone |
| 98 | /// for the parent broadcast. Returns `None` for events that aren't worth |