"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PermissionDeniedError = exports.ToolExecutionError = exports.ContextOverflowError = exports.OllamaConnectionError = exports.HarnessError = void 0;
exports.withRetry = withRetry;
exports.errorToToolResult = errorToToolResult;
class HarnessError extends Error {
    code;
    recoverable;
    constructor(message, code, recoverable = true) {
        super(message);
        this.code = code;
        this.recoverable = recoverable;
        this.name = 'HarnessError';
    }
}
exports.HarnessError = HarnessError;
class OllamaConnectionError extends HarnessError {
    constructor(message) {
        super(message, 'OLLAMA_CONNECTION', true);
    }
}
exports.OllamaConnectionError = OllamaConnectionError;
class ContextOverflowError extends HarnessError {
    constructor(tokenCount, limit) {
        super(`Context overflow: ${tokenCount} tokens exceeds ${limit} limit`, 'CONTEXT_OVERFLOW', true);
    }
}
exports.ContextOverflowError = ContextOverflowError;
class ToolExecutionError extends HarnessError {
    constructor(toolName, message) {
        super(`Tool '${toolName}': ${message}`, 'TOOL_EXECUTION', true);
    }
}
exports.ToolExecutionError = ToolExecutionError;
class PermissionDeniedError extends HarnessError {
    constructor(toolName, reason) {
        super(`Permission denied for '${toolName}': ${reason}`, 'PERMISSION_DENIED', false);
    }
}
exports.PermissionDeniedError = PermissionDeniedError;
async function withRetry(fn, maxAttempts = 3, baseDelayMs = 1000) {
    let lastError;
    for (let attempt = 1; attempt <= maxAttempts; attempt++) {
        try {
            return await fn();
        }
        catch (error) {
            lastError = error instanceof Error ? error : new Error(String(error));
            // Non-recoverable errors should not be retried
            if (error instanceof HarnessError && !error.recoverable) {
                throw error;
            }
            if (attempt < maxAttempts) {
                const delay = baseDelayMs * Math.pow(2, attempt - 1);
                await new Promise((resolve) => setTimeout(resolve, delay));
            }
        }
    }
    throw lastError;
}
function errorToToolResult(error) {
    if (error instanceof HarnessError) {
        return {
            success: false,
            output: `[${error.code}] ${error.message}`,
            error: error.message,
        };
    }
    const message = error instanceof Error ? error.message : String(error);
    return {
        success: false,
        output: `Unexpected error: ${message}`,
        error: message,
    };
}
//# sourceMappingURL=errors.js.map