/**
 * Shared logic for loading tools based on Input type.
 * This eliminates duplication between stdio.ts and processParamsGetTools.
 */

!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="149ff793-5cf7-5fdb-927a-590e09d1f4c0")}catch(e){}}();
import log from '@apify/log';
import { defaults, HelperTools } from '../const.js';
import { CATEGORY_NAMES, getCategoryTools, toolCategoriesEnabledByDefault } from '../tools/categories.js';
import { addTool } from '../tools/common/add_actor.js';
import { getActorOutput } from '../tools/common/get_actor_output.js';
import { getActorsAsTools } from '../tools/index.js';
import { SERVER_MODES } from '../types.js';
/**
 * Set of all known internal tool names across ALL modes.
 * Used for classifying selectors: if a selector matches a known internal tool name,
 * it's not treated as an Actor ID — even if it's absent from the current mode's categories.
 */
let ALL_INTERNAL_TOOL_NAMES_CACHE = null;
function getAllInternalToolNames() {
    if (!ALL_INTERNAL_TOOL_NAMES_CACHE) {
        const allNames = new Set();
        // Collect tool names from both modes to ensure complete classification
        for (const mode of SERVER_MODES) {
            const categories = getCategoryTools(mode);
            for (const name of CATEGORY_NAMES) {
                for (const tool of categories[name]) {
                    allNames.add(tool.name);
                }
            }
        }
        ALL_INTERNAL_TOOL_NAMES_CACHE = allNames;
    }
    return ALL_INTERNAL_TOOL_NAMES_CACHE;
}
/**
 * Load tools based on the provided Input object.
 * This function is used by both the stdio.ts and the processParamsGetTools function.
 *
 * @param input The processed Input object
 * @param apifyClient The Apify client instance
 * @param mode Server mode for tool variant resolution
 * @param actorStore
 * @returns An array of tool entries
 */
export async function loadToolsFromInput(input, apifyClient, mode = 'default', actorStore) {
    // Build mode-resolved categories — tools are already the correct variant for this mode
    const categories = getCategoryTools(mode);
    // Helpers for readability
    const normalizeSelectors = (value) => {
        if (value === undefined)
            return undefined;
        return (Array.isArray(value) ? value : [value])
            .map(String)
            .map((s) => s.trim())
            .filter((s) => s !== '');
    };
    const selectors = normalizeSelectors(input.tools);
    const selectorsProvided = selectors !== undefined;
    const selectorsExplicitEmpty = selectorsProvided && selectors.length === 0;
    const addActorEnabled = input.enableAddingActors === true;
    const actorsExplicitlyEmpty = (Array.isArray(input.actors) && input.actors.length === 0) || input.actors === '';
    const explicitlyNoToolsRequested = selectorsExplicitEmpty || actorsExplicitlyEmpty;
    // Build mode-specific tool-by-name map for individual tool selection
    const modeToolByName = new Map();
    for (const name of CATEGORY_NAMES) {
        for (const tool of categories[name]) {
            modeToolByName.set(tool.name, tool);
        }
    }
    // Partition selectors into internal picks (by category or by name) and Actor names
    const internalSelections = [];
    const actorSelectorsFromTools = [];
    if (selectorsProvided && !selectorsExplicitEmpty) {
        for (const selector of selectors) {
            if (selector === 'preview') {
                // 'preview' category is deprecated. It contained `call-actor` which is now default
                log.warning('Tool category "preview" is deprecated');
                const callActorTool = modeToolByName.get(HelperTools.ACTOR_CALL);
                if (callActorTool)
                    internalSelections.push(callActorTool);
                continue;
            }
            const categoryTools = categories[selector];
            if (categoryTools) {
                internalSelections.push(...categoryTools);
                continue;
            }
            const internalByName = modeToolByName.get(String(selector));
            if (internalByName) {
                internalSelections.push(internalByName);
                continue;
            }
            // If this is a known internal tool name (from another mode), skip it
            // rather than treating it as an Actor ID
            if (getAllInternalToolNames().has(String(selector))) {
                log.debug(`Skipping selector "${selector}" — it is an internal tool from another mode (current: "${mode}")`);
                continue;
            }
            // Treat unknown selectors as Actor IDs/full names.
            // Potential heuristic (future): if (String(selector).includes('/')) => definitely an Actor.
            actorSelectorsFromTools.push(String(selector));
        }
    }
    // Decide which Actors to load
    let actorsFromField;
    if (input.actors === undefined) {
        actorsFromField = undefined;
    }
    else if (Array.isArray(input.actors)) {
        actorsFromField = input.actors;
    }
    else {
        actorsFromField = [input.actors];
    }
    let actorNamesToLoad = [];
    if (actorsFromField !== undefined) {
        actorNamesToLoad = actorsFromField;
    }
    else if (actorSelectorsFromTools.length > 0) {
        actorNamesToLoad = actorSelectorsFromTools;
    }
    else if (!selectorsProvided) {
        // No selectors supplied: use defaults unless add-actor mode is enabled
        actorNamesToLoad = addActorEnabled ? [] : defaults.actors;
    } // else: selectors provided but none are actors => do not load defaults
    // Compose final tool list
    const result = [];
    // Internal tools
    if (selectorsProvided) {
        result.push(...internalSelections);
        // If add-actor mode is enabled, ensure add-actor tool is available alongside selected tools.
        if (addActorEnabled && !selectorsExplicitEmpty && !actorsExplicitlyEmpty) {
            const hasAddActor = result.some((e) => e.name === addTool.name);
            if (!hasAddActor)
                result.push(addTool);
        }
    }
    else if (addActorEnabled && !actorsExplicitlyEmpty) {
        // No selectors: either expose only add-actor (when enabled), or default categories
        result.push(addTool);
    }
    else if (!actorsExplicitlyEmpty) {
        // Use mode-resolved default categories
        for (const cat of toolCategoriesEnabledByDefault) {
            result.push(...categories[cat]);
        }
    }
    // In openai mode, unconditionally add UI-specific tools (regardless of selectors)
    if (mode === 'openai' && !explicitlyNoToolsRequested) {
        result.push(...categories.ui);
    }
    // Actor tools (if any)
    if (actorNamesToLoad.length > 0) {
        const actorTools = await getActorsAsTools(actorNamesToLoad, apifyClient, { actorStore });
        result.push(...actorTools);
    }
    /**
     * Auto-inject get-actor-run and get-actor-output when call-actor or actor tools are present.
     * Insert them right after call-actor to follow the logical workflow order:
     * search → details → call → run status → output → docs → actor tools
     *
     * Uses mode-resolved variants from getCategoryTools() for get-actor-run.
     */
    const hasCallActor = result.some((entry) => entry.name === HelperTools.ACTOR_CALL);
    const hasActorTools = result.some((entry) => entry.type === 'actor');
    const hasAddActorTool = result.some((entry) => entry.name === HelperTools.ACTOR_ADD);
    const hasGetActorRun = result.some((entry) => entry.name === HelperTools.ACTOR_RUNS_GET);
    const hasGetActorOutput = result.some((entry) => entry.name === HelperTools.ACTOR_OUTPUT_GET);
    const toolsToInject = [];
    if (!hasGetActorRun && (hasCallActor || (mode === 'openai' && !explicitlyNoToolsRequested))) {
        // Use mode-resolved get-actor-run variant
        const modeGetActorRun = modeToolByName.get(HelperTools.ACTOR_RUNS_GET);
        if (modeGetActorRun)
            toolsToInject.push(modeGetActorRun);
    }
    if (!hasGetActorOutput && (hasCallActor || hasActorTools || hasAddActorTool)) {
        toolsToInject.push(getActorOutput);
    }
    if (toolsToInject.length > 0) {
        const callActorIndex = result.findIndex((entry) => entry.name === HelperTools.ACTOR_CALL);
        if (callActorIndex !== -1) {
            result.splice(callActorIndex + 1, 0, ...toolsToInject);
        }
        else {
            result.push(...toolsToInject);
        }
    }
    // TEMP: for now we disable this swapping logic as the add-actor tool was misbehaving in some clients
    // Handle client capabilities logic for 'actors' category to swap call-actor for add-actor
    // if client supports dynamic tools.
    // const selectorContainsCallActor = selectors?.some((s) => s === HelperTools.ACTOR_CALL);
    // if (doesMcpClientSupportDynamicTools(initializeRequestData) && hasCallActor && !selectorContainsCallActor) {
    //    // Remove call-actor
    //    result = result.filter((entry) => entry.tool.name !== HelperTools.ACTOR_CALL);
    //    // Replace with add-actor if not already present
    //    if (!hasAddActorTool) result.push(addTool);
    // }
    // De-duplicate by tool name for safety
    const seen = new Set();
    return result.filter((entry) => !seen.has(entry.name) && seen.add(entry.name));
}
//# sourceMappingURL=tools_loader.js.map
//# debugId=149ff793-5cf7-5fdb-927a-590e09d1f4c0
