magi-code 0.96.1

Repository-aware CLI coding agent for terminal work
Documentation
use crate::{
    output::{
        ActivityId, ActivityMetadata, pending_tool_display_summary, tool_display_label,
        tool_display_summary,
    },
    providers::ToolCall,
    tools::ToolResult,
};
use serde_json::json;

#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub(super) struct ToolCallFingerprint {
    id: String,
    name: String,
    arguments: String,
}

impl From<&ToolCall> for ToolCallFingerprint {
    fn from(call: &ToolCall) -> Self {
        Self {
            id: call.id.clone(),
            name: call.name.clone(),
            arguments: call.arguments.to_string(),
        }
    }
}

pub(super) fn function_call_item(call: &ToolCall) -> serde_json::Value {
    json!({
        "type": "function_call",
        "call_id": call.id.clone(),
        "name": call.name.clone(),
        "arguments": arguments_json_text(&call.arguments),
        "status": "completed",
    })
}

pub(super) fn arguments_json_text(arguments: &serde_json::Value) -> String {
    match arguments {
        serde_json::Value::String(text) => text.clone(),
        value => value.to_string(),
    }
}

pub(super) fn activity_id_for_call(
    iteration: usize,
    tool_index: usize,
    call: &ToolCall,
) -> ActivityId {
    if call.id.trim().is_empty() {
        ActivityId::new(format!("turn-{iteration}/tool-{tool_index}-{}", call.name))
    } else {
        ActivityId::new(call.id.clone())
    }
}

pub(super) fn tool_activity_metadata(
    call: &ToolCall,
    result: Option<&ToolResult>,
) -> ActivityMetadata {
    let summary = result
        .map(|result| tool_display_summary(call, result))
        .or_else(|| pending_tool_display_summary(call));
    let mut metadata = ActivityMetadata::new(
        summary
            .as_ref()
            .map(|summary| summary.label.clone())
            .unwrap_or_else(|| tool_display_label(call)),
    );
    if let Some(summary) = summary {
        metadata.fields = summary.metadata;
    }
    metadata
}