magi-code 0.96.1

Repository-aware CLI coding agent for terminal work
Documentation
use super::*;

pub(super) const MAX_SUBAGENT_REPLAY_JSON_BYTES: usize = 4 * 1024 * 1024;
pub(super) const HYDRATED_SUBAGENT_DEPTH: usize = 1;

pub(super) fn hydrate_subagent_tool_call(
    ui_state: &mut state::MissionControlState,
    parent_id: &ActivityId,
    call: &ToolCall,
) {
    if call.name != tool_name::SUBAGENTS {
        return;
    }
    let Some(arguments) = parse_bounded_subagents_args(&call.arguments) else {
        return;
    };
    for (index, task) in arguments.tasks.iter().enumerate() {
        let task_id = format!("g{}", index + 1);
        ui_state.apply_historical_activity_event(ActivityEvent::Started {
            id: ActivityId::new(format!("{}/{}", parent_id.as_str(), task_id)),
            parent_id: Some(parent_id.clone()),
            kind: ActivityKind::SubagentTask,
            status: ActivityStatus::Running,
            metadata: hydrated_subagent_task_metadata(&task_id, task),
        });
    }
}

pub(super) fn hydrate_subagent_tool_result(
    ui_state: &mut state::MissionControlState,
    parent_id: &ActivityId,
    call: &ToolCall,
    result: &ToolResult,
) {
    let output = parse_bounded_subagents_output(&result.content);
    if let Some(output) = output.as_ref() {
        ensure_hydrated_subagent_parent(ui_state, parent_id, call);
        for task_result in &output.results {
            let Some(task_activity_id) =
                hydrated_subagent_task_activity_id(parent_id, &task_result.id)
            else {
                continue;
            };
            if !ui_state.nodes.contains_key(&task_activity_id) {
                ui_state.apply_historical_activity_event(ActivityEvent::Started {
                    id: task_activity_id,
                    parent_id: Some(parent_id.clone()),
                    kind: ActivityKind::SubagentTask,
                    status: ActivityStatus::Running,
                    metadata: hydrated_subagent_result_metadata(task_result),
                });
            }
        }
    }

    let task_ids = subagent_task_children(ui_state, parent_id);
    if task_ids.is_empty() {
        return;
    }

    let fallback_status = if result.success {
        ActivityStatus::Success
    } else {
        ActivityStatus::Failed
    };
    let mut reconciled = std::collections::HashSet::new();
    if let Some(output) = output {
        for task_result in &output.results {
            let Some(task_activity_id) =
                hydrated_subagent_task_activity_id(parent_id, &task_result.id)
            else {
                continue;
            };
            if !task_ids.contains(&task_activity_id) || !reconciled.insert(task_activity_id.clone())
            {
                continue;
            }
            finish_hydrated_subagent_task(
                ui_state,
                task_activity_id,
                Some(task_result),
                fallback_status,
            );
        }
    }

    for task_activity_id in task_ids {
        if !reconciled.contains(&task_activity_id) {
            finish_hydrated_subagent_task(ui_state, task_activity_id, None, fallback_status);
        }
    }
}

fn ensure_hydrated_subagent_parent(
    ui_state: &mut state::MissionControlState,
    parent_id: &ActivityId,
    call: &ToolCall,
) {
    if ui_state.nodes.contains_key(parent_id) {
        return;
    }
    ui_state.apply_historical_activity_event(ActivityEvent::Started {
        id: parent_id.clone(),
        parent_id: None,
        kind: ActivityKind::Tool,
        status: crate::output::pending_activity_status(call),
        metadata: ActivityMetadata::new(crate::output::tool_display_label(call)),
    });
}

fn subagent_task_children(
    ui_state: &state::MissionControlState,
    parent_id: &ActivityId,
) -> Vec<ActivityId> {
    ui_state
        .children
        .get(parent_id)
        .cloned()
        .unwrap_or_default()
        .into_iter()
        .filter(|id| {
            ui_state
                .nodes
                .get(id)
                .is_some_and(|node| node.kind == ActivityKind::SubagentTask)
        })
        .collect()
}

pub(super) fn finish_outstanding_subagent_tasks(
    ui_state: &mut state::MissionControlState,
    parent_id: &ActivityId,
    status: ActivityStatus,
) {
    for id in subagent_task_children(ui_state, parent_id) {
        let outstanding = ui_state.nodes.get(&id).is_some_and(|node| {
            matches!(
                node.status,
                ActivityStatus::Queued | ActivityStatus::Running | ActivityStatus::Writing
            )
        });
        if outstanding {
            ui_state.apply_historical_activity_event(ActivityEvent::Finished {
                id,
                status,
                metadata: None,
            });
        }
    }
}

fn finish_hydrated_subagent_task(
    ui_state: &mut state::MissionControlState,
    id: ActivityId,
    result: Option<&SubagentTaskResult>,
    fallback_status: ActivityStatus,
) {
    let status = result
        .map(subagent_result_activity_status)
        .unwrap_or(fallback_status);
    if let Some(result) = result {
        if let Some(usage) = result.usage {
            let request_sequence = usage.latest_request_sequence.unwrap_or_default();
            let final_usage = usage.latest_final;
            if !ui_state.session_usage.has_recorded_activity(id.as_str()) {
                ui_state
                    .session_usage
                    .observe(crate::tui::session_usage::SessionUsageRecord {
                        id: format!("legacy/activity/{}", id.as_str()),
                        usage: usage.whole_run,
                        request_sequence,
                        final_usage,
                    });
            }
            ui_state.apply_historical_activity_event(ActivityEvent::UsageSnapshot {
                id: id.clone(),
                usage,
                request_sequence,
                final_usage,
            });
        } else if !ui_state.session_usage.has_recorded_activity(id.as_str()) {
            ui_state.session_usage.incomplete = true;
        }
        ui_state.apply_historical_activity_event(ActivityEvent::FinalPreview {
            id: id.clone(),
            preview: subagent_result_preview(result),
            metadata: None,
            status: Some(status),
        });
    }
    ui_state.apply_historical_activity_event(ActivityEvent::Finished {
        id,
        status,
        metadata: None,
    });
}

fn parse_bounded_subagents_args(arguments: &serde_json::Value) -> Option<SubagentsArgs> {
    let serialized = serde_json::to_vec(arguments).ok()?;
    if serialized.len() > MAX_SUBAGENT_REPLAY_JSON_BYTES {
        return None;
    }
    let arguments: SubagentsArgs = serde_json::from_slice(&serialized).ok()?;
    arguments.validated_concurrency().ok()?;
    Some(arguments)
}

fn parse_bounded_subagents_output(content: &str) -> Option<SubagentsOutput> {
    if content.len() > MAX_SUBAGENT_REPLAY_JSON_BYTES {
        return None;
    }
    let output: SubagentsOutput = serde_json::from_str(content).ok()?;
    (output.results.len() <= MAX_SUBAGENT_TASKS).then_some(output)
}

fn hydrated_subagent_task_metadata(task_id: &str, task: &SubagentTask) -> ActivityMetadata {
    hydrated_subagent_metadata(
        task_id,
        &task.intent,
        task.identity.as_deref(),
        task.agent.as_deref(),
    )
}

fn hydrated_subagent_result_metadata(result: &SubagentTaskResult) -> ActivityMetadata {
    hydrated_subagent_metadata(
        &result.id,
        &result.intent,
        result.identity.as_deref(),
        result.agent.as_deref(),
    )
}

fn hydrated_subagent_metadata(
    task_id: &str,
    intent: &str,
    identity: Option<&str>,
    agent: Option<&str>,
) -> ActivityMetadata {
    let intent = bounded_subagent_metadata_value(intent);
    let intent = if intent.is_empty() {
        "task"
    } else {
        intent.as_str()
    };
    let label = format!("{task_id} · depth {HYDRATED_SUBAGENT_DEPTH} · {intent}");
    let mut metadata = ActivityMetadata::new(bounded_subagent_metadata_value(&label));
    metadata
        .fields
        .push(("depth".to_string(), HYDRATED_SUBAGENT_DEPTH.to_string()));
    if let Some(identity) = identity {
        let identity = bounded_subagent_metadata_value(identity);
        if !identity.is_empty() {
            metadata.fields.push(("identity".to_string(), identity));
        }
    }
    if let Some(agent) = agent {
        let agent = bounded_subagent_metadata_value(agent);
        if !agent.is_empty() {
            metadata.fields.push(("agent".to_string(), agent));
        }
    }
    metadata
}

fn bounded_subagent_metadata_value(value: &str) -> String {
    crate::tui::activity::sanitize_and_bound_preview(value)
        .split_whitespace()
        .collect::<Vec<_>>()
        .join(" ")
}

fn hydrated_subagent_task_activity_id(parent_id: &ActivityId, task_id: &str) -> Option<ActivityId> {
    let digits = task_id.strip_prefix('g')?;
    if digits.is_empty() || !digits.bytes().all(|byte| byte.is_ascii_digit()) {
        return None;
    }
    let index = digits.parse::<usize>().ok()?;
    if !(1..=MAX_SUBAGENT_TASKS).contains(&index) || format!("g{index}") != task_id {
        return None;
    }
    Some(ActivityId::new(format!(
        "{}/{}",
        parent_id.as_str(),
        task_id
    )))
}

fn subagent_result_activity_status(result: &SubagentTaskResult) -> ActivityStatus {
    match &result.status {
        SubagentStatus::Completed => ActivityStatus::Success,
        SubagentStatus::Failed => ActivityStatus::Failed,
    }
}

fn subagent_result_preview(result: &SubagentTaskResult) -> String {
    let preview = match &result.status {
        SubagentStatus::Completed => result.output.as_str(),
        SubagentStatus::Failed => result
            .error
            .as_deref()
            .filter(|error| !error.trim().is_empty())
            .unwrap_or(result.output.as_str()),
    };
    crate::tui::activity::sanitize_and_bound_preview(preview)
}