Translate selected child-loop events into a `SubagentProgress` milestone for the parent broadcast. Returns `None` for events that aren't worth surfacing as progress (text deltas, tool starts, subagent events from nested delegation, etc.). Currently emits progress for: - `ToolEnd` → `status = "tool_completed"`, `metadata = { tool, exit_code, output_bytes, error_kind? }` - `TurnEnd` → `status =
(
event: &AgentEvent,
task_id: &str,
session_id: &str,
)
| 105 | /// - `TurnEnd` → `status = "turn_completed"`, |
| 106 | /// `metadata = { turn, total_tokens, prompt_tokens, completion_tokens }` |
| 107 | fn synthesize_subagent_progress( |
| 108 | event: &AgentEvent, |
| 109 | task_id: &str, |
| 110 | session_id: &str, |
| 111 | ) -> Option<AgentEvent> { |
| 112 | match event { |
| 113 | AgentEvent::ToolEnd { |
| 114 | name, |
| 115 | output, |
| 116 | exit_code, |
| 117 | error_kind, |
| 118 | .. |
| 119 | } => { |
| 120 | let mut metadata = serde_json::json!({ |
| 121 | "tool": name, |
| 122 | "exit_code": exit_code, |
| 123 | "output_bytes": output.len(), |
| 124 | }); |
| 125 | if let Some(kind) = error_kind { |
| 126 | metadata["error_kind"] = |
| 127 | serde_json::to_value(kind).unwrap_or(serde_json::Value::Null); |
| 128 | } |
| 129 | Some(AgentEvent::SubagentProgress { |
| 130 | task_id: task_id.to_string(), |
| 131 | session_id: session_id.to_string(), |
| 132 | status: "tool_completed".to_string(), |
| 133 | metadata, |
| 134 | }) |
| 135 | } |
| 136 | AgentEvent::TurnEnd { turn, usage } => Some(AgentEvent::SubagentProgress { |
| 137 | task_id: task_id.to_string(), |
| 138 | session_id: session_id.to_string(), |
| 139 | status: "turn_completed".to_string(), |
| 140 | metadata: serde_json::json!({ |
| 141 | "turn": turn, |
| 142 | "total_tokens": usage.total_tokens, |
| 143 | "prompt_tokens": usage.prompt_tokens, |
| 144 | "completion_tokens": usage.completion_tokens, |
| 145 | }), |
| 146 | }), |
| 147 | _ => None, |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | fn task_artifact_id(result: &TaskResult) -> String { |
| 152 | format!("task-output:{}", result.task_id) |
no outgoing calls