magi-code 0.96.1

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

#[derive(Debug, Clone)]
pub(super) struct ToolRequestConfiguration {
    pub(super) disabled_tool_names: HashSet<String>,
    pub(super) subagents_tool_enabled: bool,
    pub(super) dynamic_tool_definitions: Vec<serde_json::Value>,
    /// Complete provider catalog; replaces static and dynamic definitions when present.
    pub(super) resolved_catalog: Option<Vec<serde_json::Value>>,
    pub(super) advertised_tool_names: HashSet<String>,
}

fn disabled_tool_names_for_request(tools: Option<&ToolRuntime>) -> HashSet<String> {
    let Some(tools) = tools else {
        return Default::default();
    };
    tools.disabled_tool_names().unwrap_or_else(|_| {
        crate::tools::MVP_TOOL_CAPABILITIES
            .iter()
            .map(|tool| tool.canonical_name().to_string())
            .chain(
                tools
                    .dynamic_provider_tool_definitions()
                    .into_iter()
                    .filter_map(|definition| {
                        definition
                            .get("name")
                            .and_then(serde_json::Value::as_str)
                            .map(str::to_string)
                    }),
            )
            .collect()
    })
}

pub(super) fn tool_request_configuration(tools: Option<&ToolRuntime>) -> ToolRequestConfiguration {
    if let Some(runtime) =
        tools.filter(|runtime| crate::code_mode::catalog::code_mode_available(runtime))
    {
        use crate::code_mode::catalog::{ToolCatalogSurface, effective_catalog};
        let surface = if runtime.code_mode.compact_direct_tools {
            ToolCatalogSurface::DirectProviderCompact
        } else {
            ToolCatalogSurface::DirectProviderFull
        };
        let definitions = effective_catalog(runtime, surface);
        return ToolRequestConfiguration {
            disabled_tool_names: disabled_tool_names_for_request(tools),
            subagents_tool_enabled: runtime.subagents_schema_enabled(),
            advertised_tool_names: definitions
                .iter()
                .filter_map(|entry| entry["name"].as_str().map(str::to_owned))
                .collect(),
            dynamic_tool_definitions: Vec::new(),
            resolved_catalog: Some(definitions),
        };
    }
    let (disabled_tool_names, subagents_tool_enabled, dynamic_tool_definitions) =
        if let Some(tools) = tools {
            let disabled_tool_names = disabled_tool_names_for_request(Some(tools));
            let dynamic_tool_definitions = tools
                .dynamic_provider_tool_definitions()
                .into_iter()
                .filter(|definition| {
                    definition
                        .get("name")
                        .and_then(serde_json::Value::as_str)
                        .is_some_and(|name| !disabled_tool_names.contains(name))
                })
                .collect();
            (
                disabled_tool_names,
                tools.subagents_schema_enabled(),
                dynamic_tool_definitions,
            )
        } else {
            (HashSet::new(), true, Vec::new())
        };

    let mut advertised_tool_names = crate::tools::MVP_TOOL_CAPABILITIES
        .iter()
        .filter(|tool| {
            (subagents_tool_enabled || **tool != crate::tools::ToolCapability::Subagents)
                && !disabled_tool_names.contains(tool.canonical_name())
        })
        .map(|tool| tool.canonical_name().to_string())
        .collect::<HashSet<_>>();
    for definition in &dynamic_tool_definitions {
        if let Some(name) = definition.get("name").and_then(serde_json::Value::as_str) {
            advertised_tool_names.insert(name.to_string());
        }
    }

    ToolRequestConfiguration {
        disabled_tool_names,
        subagents_tool_enabled,
        dynamic_tool_definitions,
        resolved_catalog: None,
        advertised_tool_names,
    }
}