All files / kernel-agents-repl/src/strategies/repl evaluator-error.ts

100% Statements 19/19
100% Branches 20/20
100% Functions 5/5
100% Lines 19/19

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68                      2x 13x 3x   10x           2x 7x   2x 7x     2x 5x                         2x       24x 16x   8x     8x 1x       7x 3x             4x    
import { SampleGenerationError, EvaluatorError } from '@metamask/kernel-errors';
 
import type { EvaluationResult } from './prepare-evaluation.ts';
import { ERROR } from './symbols.ts';
 
/**
 * Strips stack traces from an error while preserving the message and cause chain.
 *
 * @param error - The error to strip stack traces from.
 * @returns The error without stack traces.
 */
export const stripStackTrace = (error: unknown): unknown => {
  if (!(error instanceof Error)) {
    return error;
  }
  return new Error(
    error.message,
    ...(error.cause ? [{ cause: stripStackTrace(error.cause) }] : []),
  );
};
 
const asError = (error: unknown): Error =>
  error instanceof Error ? error : new Error(String(error));
 
const isSyntaxError = (error: unknown): boolean =>
  error instanceof SyntaxError ||
  (error instanceof Error && error.name === 'SyntaxError');
 
const isReferenceError = (error: unknown): boolean =>
  error instanceof ReferenceError ||
  (error instanceof Error && error.name === 'ReferenceError');
 
/**
 * Processes any error in the evaluation result. If an error exists, classifies it
 * and either throws (for retry/exit errors) or processes and assigns it back to
 * the result (for valid feedback errors).
 *
 * @param result - The evaluation result object that may contain an error.
 * @param code - The code that was being evaluated.
 * @throws {SampleGenerationError} For syntax/reference errors that should trigger retry.
 * @throws {EvaluatorError} For internal errors that should exit the attempt.
 */
export const processEvaluationError = (
  result: EvaluationResult,
  code: string,
): void => {
  if (!Object.hasOwn(result, ERROR)) {
    return;
  }
  const error = result[ERROR];
 
  // Check if this is already an EvaluatorError (thrown by safe wrappers)
  if (error instanceof EvaluatorError) {
    throw error;
  }
 
  // Check if this is a sample generation error (syntax/reference errors)
  if (isSyntaxError(error) || isReferenceError(error)) {
    throw new SampleGenerationError(
      code,
      stripStackTrace(asError(error)) as Error,
    );
  }
 
  // All other errors are valid feedback (capability errors, NotImplemented, etc.)
  result[ERROR] = stripStackTrace(asError(error));
};