import { safeJsonStringify } from "../../../util/log-sanitizer.js";
/**
 * Tool categories for grouping and middleware selection.
 */
export var ToolCategory;
(function (ToolCategory) {
    ToolCategory["FILE"] = "file";
    ToolCategory["COMPONENT"] = "component";
    ToolCategory["MULTI_FILE"] = "multi_file";
    ToolCategory["GENERAL"] = "general";
    ToolCategory["API"] = "api";
    ToolCategory["SUBAGENT"] = "subagent";
    ToolCategory["METADATA"] = "metadata";
    ToolCategory["DATA"] = "data";
    ToolCategory["MEMORY"] = "memory";
    ToolCategory["PLAN"] = "plan";
    ToolCategory["TEST"] = "test";
    ToolCategory["DEBUG"] = "debug";
})(ToolCategory || (ToolCategory = {}));
/**
 * Permission levels for tool execution.
 */
export var PermissionLevel;
(function (PermissionLevel) {
    /** Execute immediately without user interaction */
    PermissionLevel["ALLOW"] = "allow";
    /** Prompt user for confirmation before execution */
    PermissionLevel["PROMPT"] = "prompt";
    /** Block execution completely */
    PermissionLevel["BLOCK"] = "block";
})(PermissionLevel || (PermissionLevel = {}));
/**
 * Helper function to create a tool factory without name duplication.
 *
 * The name is defined once and automatically injected into the tool,
 * eliminating the need to repeat it in the tool definition.
 *
 * Provides full type inference from Zod schemas - input and output types
 * are automatically inferred from inputSchema and outputSchema.
 *
 * @param name - Unique tool name
 * @param factory - Factory function that receives dependencies and returns a tool (without name)
 * @returns Tool factory with full type inference
 *
 * @example
 * const myTool = createToolFactory('my-tool', (deps) => ({
 *   description: 'Does something',
 *   category: 'utilities',
 *   inputSchema: z.object({ count: z.number() }),
 *   outputSchema: z.object({ result: z.string() }),
 *   execute: async (input) => {
 *     // input is typed as { count: number }
 *     // return type must be { result: string }
 *     return { result: String(input.count) };
 *   }
 * }));
 */
export function createToolFactory(name, factory) {
    return {
        name,
        create: (deps) => ({ ...factory(deps), name }),
    };
}
export class ToolExecutionError extends Error {
    name = "ToolExecutionError";
    options;
    _message;
    constructor(messageOrOptions, options) {
        // Call super with empty string - the getter will compute the full message
        super("");
        let message;
        let opts;
        if (typeof messageOrOptions === "string") {
            message = messageOrOptions;
            opts = options;
        }
        else {
            opts = messageOrOptions;
        }
        this._message = message;
        this.options = opts;
        // Override the message property to use our getter
        Object.defineProperty(this, "message", {
            get: () => this.getMessage(),
            configurable: true,
        });
    }
    getMessage() {
        let message = "Error executing tool";
        if (this.options) {
            message += ` "${this.options.toolName}"`;
        }
        if (this._message) {
            message += `: ${this._message}`;
        }
        // Include cause message if available.
        // When the cause is another ToolExecutionError, only include its core
        // error text to avoid duplicating the serialized input/context data
        // that this error will append below.
        if (this.cause instanceof ToolExecutionError) {
            const causeErrorText = this.cause.getErrorText();
            if (causeErrorText) {
                message += `: ${causeErrorText}`;
            }
        }
        else if (this.cause instanceof Error) {
            message += `: ${this.cause.message}`;
        }
        else if (this.cause &&
            typeof this.cause === "object" &&
            "message" in this.cause) {
            message += `: ${String(this.cause.message)}`;
        }
        if (this.options) {
            message += `\ninput: ${safeJsonStringify(this.options.input, 2)}`;
            message += `\ncontext: ${safeJsonStringify(this.options.context, 2)}`;
        }
        return message;
    }
    /**
     * Returns only the descriptive error text from this error and its cause chain,
     * without serialized input/context. Used to prevent duplication when this error
     * is nested as a cause of another ToolExecutionError.
     */
    getErrorText() {
        const parts = [];
        if (this._message) {
            parts.push(this._message);
        }
        if (this.cause instanceof ToolExecutionError) {
            const nested = this.cause.getErrorText();
            if (nested)
                parts.push(nested);
        }
        else if (this.cause instanceof Error) {
            parts.push(this.cause.message);
        }
        else if (this.cause &&
            typeof this.cause === "object" &&
            "message" in this.cause) {
            parts.push(String(this.cause.message));
        }
        return parts.join(": ");
    }
    get code() {
        return this.options?.code;
    }
    get toolName() {
        return this.options?.toolName;
    }
    get severity() {
        return this.options?.severity ?? "error";
    }
    get input() {
        return this.options?.input;
    }
    get message() {
        return this.getMessage();
    }
    get stack() {
        if (this.cause instanceof Error) {
            return this.cause.stack;
        }
        return undefined;
    }
    get cause() {
        return this.options?.cause;
    }
    /**
     * Custom JSON serialization to ensure the message getter is included.
     * This is necessary because JSON.stringify doesn't serialize getters by default.
     */
    toJSON() {
        return {
            name: this.name,
            message: this.message, // Call the getter to compute the message
            toolName: this.toolName,
            input: this.input,
            severity: this.severity,
            cause: this.cause instanceof Error
                ? {
                    name: this.cause.name,
                    message: this.cause.message,
                    stack: this.cause.stack,
                }
                : this.cause,
            stack: this.stack,
        };
    }
}
//# sourceMappingURL=types.js.map