// Tool error taxonomy, mirroring gateway/harness/workspace (ADR-0003/0004/0005/0006).
// Errors carry a stable `code` discriminant; callers switch on `code`, never parse `message`.
// Every message is redacted at construction so errors are always safe to log or surface.
import { redact } from "../redaction.js";
export const TOOL_CODES = {
    ARGUMENT: "TOOL_ARGUMENT",
    UNKNOWN: "TOOL_UNKNOWN",
    COMMAND_DENIED: "TOOL_COMMAND_DENIED",
    COMMAND_TIMEOUT: "TOOL_COMMAND_TIMEOUT",
    COMMAND_CANCELLED: "TOOL_COMMAND_CANCELLED",
    OUTPUT_LIMIT: "TOOL_OUTPUT_LIMIT",
    PATCH_INVALID: "TOOL_PATCH_INVALID",
    PATCH_APPLY_DISABLED: "TOOL_PATCH_APPLY_DISABLED",
    PATCH_APPLY_FAILED: "TOOL_PATCH_APPLY_FAILED",
};
export class ToolError extends Error {
    constructor(message, secrets = []) {
        super(redact(message, secrets));
        this.name = new.target.name;
    }
}
// Malformed tool arguments (a required field missing or of the wrong type).
export class ToolArgumentError extends ToolError {
    code = TOOL_CODES.ARGUMENT;
    toolName;
    constructor(message, toolName, secrets = []) {
        super(message, secrets);
        this.toolName = toolName;
    }
}
// No such tool in the host's dispatch map.
export class UnknownToolError extends ToolError {
    code = TOOL_CODES.UNKNOWN;
    toolName;
    constructor(message, toolName, secrets = []) {
        super(message, secrets);
        this.toolName = toolName;
    }
}
// Executable or subcommand not on the allowlist (deny-by-default). Raised BEFORE any spawn.
export class CommandDeniedError extends ToolError {
    code = TOOL_CODES.COMMAND_DENIED;
    executable;
    constructor(message, executable, secrets = []) {
        super(message, secrets);
        this.executable = executable;
    }
}
// The command exceeded its wall-time budget and was terminated.
export class CommandTimeoutError extends ToolError {
    code = TOOL_CODES.COMMAND_TIMEOUT;
    timeoutMs;
    constructor(message, timeoutMs, secrets = []) {
        super(message, secrets);
        this.timeoutMs = timeoutMs;
    }
}
// Abort-driven cancellation of a command or a patch apply.
export class CommandCancelledError extends ToolError {
    code = TOOL_CODES.COMMAND_CANCELLED;
}
// A hard output-limit breach (used where truncate-and-flag is not acceptable, e.g. patch input).
export class OutputLimitError extends ToolError {
    code = TOOL_CODES.OUTPUT_LIMIT;
    limitBytes;
    constructor(message, limitBytes, secrets = []) {
        super(message, secrets);
        this.limitBytes = limitBytes;
    }
}
// Patch validation failed; carries the structured rejection reasons. Nothing was written.
export class PatchValidationError extends ToolError {
    code = TOOL_CODES.PATCH_INVALID;
    reasons;
    conflicts;
    constructor(message, reasons, conflicts, secrets = []) {
        super(message, secrets);
        this.reasons = reasons;
        this.conflicts = conflicts;
    }
}
// Fail-closed: apply requested while applyEnabled is false. Nothing was written.
export class PatchApplyDisabledError extends ToolError {
    code = TOOL_CODES.PATCH_APPLY_DISABLED;
}
// A write (or rollback) failed during the apply phase at the filesystem boundary.
export class PatchApplyError extends ToolError {
    code = TOOL_CODES.PATCH_APPLY_FAILED;
    path;
    constructor(message, path, secrets = []) {
        super(message, secrets);
        this.path = path;
    }
}
