/**
 * execute_tool — meta-tool for dynamic tool execution.
 *
 * Executes a tool by name with the specified parameters. Requires
 * get_tool_info to have been called first for the target tool.
 *
 * Modeled after backend/agent/tools/execute_tool.py.
 */
import { Type } from '@sinclair/typebox';
import { EXECUTE_TOOL } from '../../tool-names.js';
// ---------------------------------------------------------------------------
// Schema
// ---------------------------------------------------------------------------
const schema = Type.Object({
    tool_name: Type.String({
        description: 'The name of the tool to execute (must call get_tool_info first)'
    }),
    parameters: Type.Record(Type.String(), Type.Unknown(), {
        description: 'Dictionary of parameters to pass to the tool. Keys must match the parameter names from get_tool_info.'
    })
});
// ---------------------------------------------------------------------------
// Auto-nesting fix
// ---------------------------------------------------------------------------
/**
 * Auto-fix when LLM passes target tool params flat instead of nested in 'parameters'.
 * Example: { tool_name: "loop", action: "start" } → { tool_name: "loop", parameters: { action: "start" } }
 */
function autoNestFlatParameters(raw) {
    if ('parameters' in raw) {
        return raw;
    }
    const knownFields = new Set(['tool_name']);
    const extra = {};
    for (const [key, value] of Object.entries(raw)) {
        if (!knownFields.has(key)) {
            extra[key] = value;
        }
    }
    if (Object.keys(extra).length > 0 && typeof raw.tool_name === 'string') {
        return {
            tool_name: raw.tool_name,
            parameters: extra
        };
    }
    return raw;
}
// ---------------------------------------------------------------------------
// Description
// ---------------------------------------------------------------------------
const DESCRIPTION = `Execute a tool by name with the specified parameters.
You MUST call get_tool_info first to understand parameters before using execute_tool. Include all required parameters.

IMPORTANT: All target tool parameters MUST be nested inside the 'parameters' dict — do NOT pass them as top-level keys.
Correct: {"tool_name": "loop", "parameters": {"action": "start", "prompt": "check staging"}}
Wrong: {"tool_name": "loop", "action": "start", "prompt": "check staging"}`;
// ---------------------------------------------------------------------------
// Factory
// ---------------------------------------------------------------------------
export function createExecuteToolTool(registry) {
    return {
        name: EXECUTE_TOOL,
        label: 'Execute Tool',
        isReadOnly: false,
        description: DESCRIPTION,
        parameters: schema,
        async execute(toolCallId, rawParams, signal, onUpdate, ctx) {
            const params = autoNestFlatParameters(rawParams);
            const { tool_name, parameters } = params;
            // Find the tool
            const entry = registry.find((e) => e.definition.name === tool_name);
            if (!entry) {
                const available = registry.map((e) => e.definition.name).join(', ');
                const text = `Tool '${tool_name}' not found. Available: ${available}`;
                return { content: [{ type: 'text', text }], details: undefined };
            }
            // Execute the target tool
            try {
                return await entry.definition.execute(toolCallId, parameters, signal, onUpdate, ctx);
            }
            catch (err) {
                const msg = err instanceof Error ? err.message : String(err);
                const text = `Error executing tool '${tool_name}': ${msg}`;
                return { content: [{ type: 'text', text }], details: undefined };
            }
        }
    };
}
//# sourceMappingURL=execute-tool.js.map