/** * Error handling type definitions for adapters * * This module provides types for building flexible, pattern-based error * translation systems. Error patterns allow declarative error handling that * is easier to understand and maintain than scattered if-else logic. * * ## Core Concepts * * **Error Matcher**: Determines if an error matches a pattern * - String: Case-insensitive substring match * - RegExp: Pattern match against error.message * - Function: Custom predicate for complex matching * * **Error Pattern**: Maps errors to structured CoachingErrors * - Includes matching rule, error code, hints, and fix suggestions * - Supports context-aware error messages * - Enables recovery strategies * * **Error Mapper**: Translates errors using patterns * - Builds error patterns declaratively * - Applies patterns in order (first match wins) * - Falls back to defaults if no pattern matches * * ## Design Principles * * 1. **Declarative over Imperative**: Define all error scenarios upfront * 2. **Type-Safe**: Full TypeScript support with no implicit any * 3. **Reusable**: Share patterns across adapters * 4. **Extensible**: Add new patterns without modifying control flow * * @example Pattern-based error mapping * ```typescript * const mapper = new ErrorMapper({ * defaultCode: "UNKNOWN_ERROR", * defaultHint: "An unexpected error occurred" * }); * * mapper.addPattern({ * match: "ECONNREFUSED", * code: "CONNECTION_FAILED", * hint: "Server connection failed", * fix: "Check server is running" * }); * * try { * // operation * } catch (error) { * throw mapper.map(error, { operation: "connect" }); * } * ``` * * @example Regex matching with context * ```typescript * mapper.addPattern({ * match: /timeout|timed out/i, * code: "OPERATION_TIMEOUT", * messageTemplate: "Operation timed out: {message}", * hint: "The operation took too long", * fix: "Increase timeout or check for performance issues" * }); * ``` * * @example Custom predicate matching * ```typescript * mapper.addPattern({ * match: (error) => error.code === "ENOTFOUND", * code: "ADAPTER_CONNECTION_FAILED", * hint: "Server hostname could not be resolved", * fix: "Check baseUrl configuration" * }); * ``` * * @module @wavespec/kit/error */ import type { RecoveryStrategy, ErrorSeverity } from "@wavespec/types"; /** * Error matcher for pattern matching strategies * * Used to determine if an error matches an ErrorPattern. * Supports three matching strategies: * * 1. **String matcher**: Case-insensitive substring search in error.message * - Fast, simple, good for exact matches * - Best for: common error messages you know well * * 2. **RegExp matcher**: Pattern match against error.message * - Flexible, powerful, best for variations * - Best for: similar errors with variations (e.g., "timed out", "timeout") * * 3. **Function matcher**: Custom predicate function * - Maximum flexibility for complex logic * - Best for: errors where message doesn't tell full story (need to check error.code, properties, etc.) * * @example String matcher * ```typescript * match: "ECONNREFUSED" // Matches if error.message includes "ECONNREFUSED" * ``` * * @example RegExp matcher * ```typescript * match: /econnrefused|enotfound/i // Case-insensitive pattern * ``` * * @example Function matcher * ```typescript * match: (error) => error.code === "ENOTFOUND" || error.code === "ECONNREFUSED" * ``` */ export type ErrorMatcher = string | RegExp | ((error: Error) => boolean); /** * Error pattern definition for matching and translating errors * * An ErrorPattern defines all the information needed to: * 1. Recognize when an error matches this pattern * 2. Translate it to a structured CoachingError * 3. Provide actionable guidance to the user * 4. Suggest recovery strategies * * Patterns are matched in order (first match wins), so arrange * specific patterns before generic ones. * * @example Complete error pattern * ```typescript * const pattern: ErrorPattern = { * match: /econnrefused|enotfound/i, * code: "ADAPTER_CONNECTION_FAILED", * messageTemplate: "Failed to connect to server: {message}", * hint: "The server is not reachable. This usually means:\n • The server is not running\n • The hostname/port is incorrect\n • A firewall is blocking the connection", * fix: "Check that the server is running and accessible. Verify the baseUrl in adapter config.", * severity: "error", * learnMore: "https://docs.example.com/troubleshooting/connection-errors", * extractContext: (error) => ({ * code: (error as any).code, * syscall: (error as any).syscall, * }), * recovery: { * type: "retry", * params: { * maxAttempts: 3, * backoffMs: 1000 * } * } * }; * ``` */ export interface ErrorPattern { /** * Pattern matcher - determines if an error matches this pattern * * Matching strategy: * - String: Case-insensitive substring match in error.message * - RegExp: Pattern match in error.message * - Function: Custom predicate (error: Error) => boolean * * Patterns are tried in order, first match wins. */ match: ErrorMatcher; /** * Error code for CoachingError * * Should be from ERROR_CODES constant or a custom code. * Used for programmatic error handling and categorization. * * @example "ADAPTER_CONNECTION_FAILED" * @example "OPERATION_TIMEOUT" */ code: string; /** * Message template with interpolation support * * If provided, used instead of the original error message. * Supports {field} interpolation from error object properties. * Common fields: {message}, {code}, {errno}, {syscall} * * If not provided, uses the original error.message as-is. * * @example "Failed to connect: {message}" * @example "Operation {operation} timed out after {timeout}ms" */ messageTemplate?: string; /** * Human-readable hint explaining what went wrong * * Should explain the root cause, not just repeat the error. * Help users understand why this error happened. * Can include multiple bullet points for complex errors. * * @example "The server refused the connection. This usually means the server is not running or the port is incorrect." */ hint: string; /** * Suggested fix or next action * * Provide concrete steps to resolve the error. * Be specific and actionable. * Can include multiple steps for complex fixes. * * @example "Check that the server is running. Verify the baseUrl in adapter config." */ fix?: string; /** * Error severity level * * Indicates how serious this error is: * - "error": Critical failure, test cannot continue (default) * - "warn": Non-critical, test can continue with reduced functionality * - "info": Informational message, no failure * * @default "error" */ severity?: ErrorSeverity; /** * Documentation link for learning more * * Should link to relevant documentation, troubleshooting guides, * or protocol specifications that explain this error in detail. * * @example "https://docs.example.com/troubleshooting/timeouts" */ learnMore?: string; /** * Extract additional context from the error * * Called to extract error-specific details that should be included * in the resulting CoachingError.context for debugging. * * Use this to extract important error properties like: * - error.code (network error code like ECONNREFUSED) * - error.syscall (system call that failed) * - error.errno (system error number) * - Custom properties added by SDK * * The extracted context is merged with the original context * passed to the error mapper. * * @example * ```typescript * extractContext: (error) => ({ * code: (error as any).code, * syscall: (error as any).syscall, * }) * ``` */ extractContext?: (error: Error) => Record; /** * Recovery strategy for automated error handling * * Provides guidance for automated recovery without human intervention. * Enables agents to: * - Retry failed operations with backoff * - Fall back to alternative operations * - Skip problematic tests and continue * - Mark errors that require manual intervention * * @example Retry strategy * ```typescript * recovery: { * type: "retry", * params: { * maxAttempts: 3, * backoffMs: 1000 * } * } * ``` * * @example Manual recovery * ```typescript * recovery: { * type: "manual", * params: { * manualSteps: [ * "Check server logs for details", * "Restart the server", * "Re-run the test" * ] * } * } * ``` */ recovery?: RecoveryStrategy; } /** * Configuration for error mapper initialization * * Provides default values for errors that don't match any pattern. * Used by error mappers to handle unexpected errors gracefully. * * @example * ```typescript * const config: ErrorMapperConfig = { * defaultCode: "TEST_EXECUTION_ERROR", * defaultHint: "An unexpected error occurred during test execution", * defaultFix: "Enable debug logging to capture more details about the error" * }; * ``` */ export interface ErrorMapperConfig { /** * Default error code for unmatched errors * * Used when an error doesn't match any pattern. * Should be a general error code that indicates the error type. * * @example "UNKNOWN_ERROR" * @example "TEST_EXECUTION_ERROR" */ defaultCode: string; /** * Default hint for unmatched errors * * Used when an error doesn't match any pattern. * Should provide general guidance for unexpected errors. * * @example "An unexpected error occurred that doesn't match known error patterns" */ defaultHint: string; /** * Default fix for unmatched errors * * Optional. Provides general guidance on what to do with unexpected errors. * * @example "Enable debug logging to capture more error details" */ defaultFix?: string; } /** * Error context passed to error mapper * * Provides additional information about the context where an error occurred. * Used for: * - Adding operation context to error messages * - Entity-specific error messages (tool name, prompt name, resource URI) * - Request/response details for debugging * - User information for audit trails * * Context is merged with extracted context from the error pattern * and included in the final CoachingError.context. * * @example Operation context * ```typescript * const context: ErrorContext = { * operation: "list_tools", * version: "1.0.0" * }; * ``` * * @example Entity-specific context * ```typescript * const context: ErrorContext = { * operation: "call_tool", * toolName: "get_weather", * toolVersion: "1.0" * }; * ``` * * @example Request context * ```typescript * const context: ErrorContext = { * operation: "http_request", * method: "POST", * url: "https://api.example.com/data", * status: 500 * }; * ``` */ export interface ErrorContext { /** * Current operation being executed * * Provides context about what was being done when the error occurred. * Helps users understand the operation's context and expected behavior. * * @example "connect" * @example "list_tools" * @example "call_tool" */ operation?: string; /** * Additional context fields * * Open-ended object for adapter-specific context. * Common fields: * - toolName: Name of tool being called * - promptName: Name of prompt being used * - resourceUri: URI of resource being accessed * - method: HTTP method (for HTTP adapter) * - url: Request URL (for HTTP adapter) * - status: HTTP status code * - version: Protocol/API version */ [key: string]: unknown; } /** * Result of error mapping * * The final structured error after pattern matching and context extraction. * This is what adapters throw after translating raw errors. * * MappedError is actually a CoachingError from @wavespec/types, * but this type documents what properties the mapped error should contain. * * @example * ```typescript * const error = errorMapper.map(originalError, { operation: "connect" }); * // error is a CoachingError with: * // - code: "ADAPTER_CONNECTION_FAILED" * // - message: "Failed to connect to server" * // - hint: "The server refused the connection..." * // - fix: "Check that the server is running..." * // - context: { operation: "connect", originalError: "..." } * ``` */ export interface MappedError { /** * Error code for programmatic handling * * Machine-readable code that identifies the error type. * Used for error categorization, monitoring, and programmatic handling. * * @example "ADAPTER_CONNECTION_FAILED" */ code: string; /** * Human-readable error message * * Describes what went wrong in user-friendly language. * Should be clear and specific. * * @example "Failed to connect to server: Connection refused" */ message: string; /** * Hint explaining the root cause * * Additional context about why the error occurred. * Helps users understand the underlying issue. * * @example "The server is not reachable. Check that it's running and the hostname is correct." */ hint?: string; /** * Suggested fix or next action * * Concrete steps the user can take to resolve the error. * * @example "Verify the baseUrl in adapter config and ensure the server is running" */ fix?: string; /** * Error severity level * * - "error": Critical, test cannot continue * - "warn": Non-critical, test can continue * - "info": Informational only * * @default "error" */ severity: ErrorSeverity; /** * Documentation link * * URL to relevant documentation, guide, or specification. * * @example "https://docs.example.com/troubleshooting/connection-errors" */ learnMore?: string; /** * Context data for debugging * * Additional information extracted from the error and context. * Includes: * - originalError: The original error message * - errorName: The error class name * - Extracted context from pattern * - Provided context from caller * * @example { originalError: "ECONNREFUSED", operation: "connect", code: "ECONNREFUSED" } */ context?: Record; /** * Recovery strategy for automated handling * * Provides guidance for automated recovery (retries, fallbacks, etc.) * without human intervention. * * @example { type: "retry", params: { maxAttempts: 3, backoffMs: 1000 } } */ recovery?: RecoveryStrategy; } //# sourceMappingURL=types.d.ts.map