{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}

{- |
Module      : Langchain.Error
Description : Central error handling for langchain-hs
Copyright   : (c) 2025 Tushar Adhatrao
License     : MIT
Maintainer  : Tushar Adhatrao <tusharadhatrao@gmail.com>
Stability   : experimental

This module provides a comprehensive error handling system for langchain-hs,
replacing the previous `Either String` pattern with a structured, type-safe
approach that follows industry best practices.

The error system includes:

* Structured error types with context and metadata
* Error severity levels and categories
* Utility functions for error construction and handling
* Integration with existing langchain-hs components
* Support for error chaining and context preservation

Example usage:

@
import Langchain.Error

-- Creating errors
let err = llmError "Model timeout" (Just "gpt-4") Nothing

-- Error handling with context
result <- someOperation
case result of
  Left err -> do
    logError err
    handleError err
  Right value -> processValue value

-- Error chaining
chainError "Failed to process document" originalError
@
-}
module Langchain.Error
  ( -- * Error Types
    LangchainError (..)
  , ErrorSeverity (..)
  , ErrorCategory (..)
  , ErrorContext (..)

    -- * Error Construction
  , llmError
  , llmErrorWithContext
  , agentError
  , agentErrorWithContext
  , memoryError
  , memoryErrorWithContext
  , toolError
  , toolErrorWithContext
  , vectorStoreError
  , vectorStoreErrorWithContext
  , documentLoaderError
  , documentLoaderErrorWithContext
  , embeddingError
  , embeddingErrorWithContext
  , runnableError
  , runnableErrorWithContext
  , parsingError
  , parsingErrorWithContext
  , networkError
  , networkErrorWithContext
  , configurationError
  , configurationErrorWithContext
  , validationError
  , validationErrorWithContext
  , internalError
  , internalErrorWithContext

    -- * Error Utilities
  , chainError
  , addContext
  , withErrorContext
  , mapError
  , fromString
  , toString
  , toText
  , logError
  , isRetryable
  , getSeverity
  , getCategory
  , fromStringError
  , fromException
  , liftStringError
  , simpleError
  , catchToLangchainError
  , withContext
  , withContextIO

    -- * Type Aliases
  , LangchainResult
  , LangchainIO

    -- * Re-exports for convenience
  , module Control.Exception
  ) where

import Control.Exception (Exception, SomeException, displayException, try)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.Aeson (FromJSON, ToJSON)
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import qualified Data.Text as T
import Data.Time (UTCTime, getCurrentTime)
import GHC.Generics (Generic)
import System.IO (hPutStrLn, stderr)

-- | Severity levels for errors, following industry standards
data ErrorSeverity
  = -- | System-breaking errors that require immediate attention
    Critical
  | -- | Errors that prevent core functionality
    High
  | -- | Errors that degrade functionality but allow continuation
    Medium
  | -- | Minor errors or warnings
    Low
  | -- | Informational messages
    Info
  deriving (ErrorSeverity -> ErrorSeverity -> Bool
(ErrorSeverity -> ErrorSeverity -> Bool)
-> (ErrorSeverity -> ErrorSeverity -> Bool) -> Eq ErrorSeverity
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ErrorSeverity -> ErrorSeverity -> Bool
== :: ErrorSeverity -> ErrorSeverity -> Bool
$c/= :: ErrorSeverity -> ErrorSeverity -> Bool
/= :: ErrorSeverity -> ErrorSeverity -> Bool
Eq, Eq ErrorSeverity
Eq ErrorSeverity =>
(ErrorSeverity -> ErrorSeverity -> Ordering)
-> (ErrorSeverity -> ErrorSeverity -> Bool)
-> (ErrorSeverity -> ErrorSeverity -> Bool)
-> (ErrorSeverity -> ErrorSeverity -> Bool)
-> (ErrorSeverity -> ErrorSeverity -> Bool)
-> (ErrorSeverity -> ErrorSeverity -> ErrorSeverity)
-> (ErrorSeverity -> ErrorSeverity -> ErrorSeverity)
-> Ord ErrorSeverity
ErrorSeverity -> ErrorSeverity -> Bool
ErrorSeverity -> ErrorSeverity -> Ordering
ErrorSeverity -> ErrorSeverity -> ErrorSeverity
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: ErrorSeverity -> ErrorSeverity -> Ordering
compare :: ErrorSeverity -> ErrorSeverity -> Ordering
$c< :: ErrorSeverity -> ErrorSeverity -> Bool
< :: ErrorSeverity -> ErrorSeverity -> Bool
$c<= :: ErrorSeverity -> ErrorSeverity -> Bool
<= :: ErrorSeverity -> ErrorSeverity -> Bool
$c> :: ErrorSeverity -> ErrorSeverity -> Bool
> :: ErrorSeverity -> ErrorSeverity -> Bool
$c>= :: ErrorSeverity -> ErrorSeverity -> Bool
>= :: ErrorSeverity -> ErrorSeverity -> Bool
$cmax :: ErrorSeverity -> ErrorSeverity -> ErrorSeverity
max :: ErrorSeverity -> ErrorSeverity -> ErrorSeverity
$cmin :: ErrorSeverity -> ErrorSeverity -> ErrorSeverity
min :: ErrorSeverity -> ErrorSeverity -> ErrorSeverity
Ord, Int -> ErrorSeverity -> ShowS
[ErrorSeverity] -> ShowS
ErrorSeverity -> String
(Int -> ErrorSeverity -> ShowS)
-> (ErrorSeverity -> String)
-> ([ErrorSeverity] -> ShowS)
-> Show ErrorSeverity
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ErrorSeverity -> ShowS
showsPrec :: Int -> ErrorSeverity -> ShowS
$cshow :: ErrorSeverity -> String
show :: ErrorSeverity -> String
$cshowList :: [ErrorSeverity] -> ShowS
showList :: [ErrorSeverity] -> ShowS
Show, (forall x. ErrorSeverity -> Rep ErrorSeverity x)
-> (forall x. Rep ErrorSeverity x -> ErrorSeverity)
-> Generic ErrorSeverity
forall x. Rep ErrorSeverity x -> ErrorSeverity
forall x. ErrorSeverity -> Rep ErrorSeverity x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ErrorSeverity -> Rep ErrorSeverity x
from :: forall x. ErrorSeverity -> Rep ErrorSeverity x
$cto :: forall x. Rep ErrorSeverity x -> ErrorSeverity
to :: forall x. Rep ErrorSeverity x -> ErrorSeverity
Generic, [ErrorSeverity] -> Value
[ErrorSeverity] -> Encoding
ErrorSeverity -> Bool
ErrorSeverity -> Value
ErrorSeverity -> Encoding
(ErrorSeverity -> Value)
-> (ErrorSeverity -> Encoding)
-> ([ErrorSeverity] -> Value)
-> ([ErrorSeverity] -> Encoding)
-> (ErrorSeverity -> Bool)
-> ToJSON ErrorSeverity
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
$ctoJSON :: ErrorSeverity -> Value
toJSON :: ErrorSeverity -> Value
$ctoEncoding :: ErrorSeverity -> Encoding
toEncoding :: ErrorSeverity -> Encoding
$ctoJSONList :: [ErrorSeverity] -> Value
toJSONList :: [ErrorSeverity] -> Value
$ctoEncodingList :: [ErrorSeverity] -> Encoding
toEncodingList :: [ErrorSeverity] -> Encoding
$comitField :: ErrorSeverity -> Bool
omitField :: ErrorSeverity -> Bool
ToJSON, Maybe ErrorSeverity
Value -> Parser [ErrorSeverity]
Value -> Parser ErrorSeverity
(Value -> Parser ErrorSeverity)
-> (Value -> Parser [ErrorSeverity])
-> Maybe ErrorSeverity
-> FromJSON ErrorSeverity
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser ErrorSeverity
parseJSON :: Value -> Parser ErrorSeverity
$cparseJSONList :: Value -> Parser [ErrorSeverity]
parseJSONList :: Value -> Parser [ErrorSeverity]
$comittedField :: Maybe ErrorSeverity
omittedField :: Maybe ErrorSeverity
FromJSON)

-- | Categories of errors for better organization and handling
data ErrorCategory
  = -- | Language model related errors
    LLMError
  | -- | Agent execution errors
    AgentError
  | -- | Memory management errors
    MemoryError
  | -- | Tool execution errors
    ToolError
  | -- | Vector store operation errors
    VectorStoreError
  | -- | Document loading errors
    DocumentLoaderError
  | -- | Embedding generation errors
    EmbeddingError
  | -- | Runnable execution errors
    RunnableError
  | -- | Data parsing and validation errors
    ParsingError
  | -- | Network and HTTP errors
    NetworkError
  | -- | Configuration and setup errors
    ConfigurationError
  | -- | Input validation errors
    ValidationError
  | -- | Internal system errors
    InternalError
  deriving (ErrorCategory -> ErrorCategory -> Bool
(ErrorCategory -> ErrorCategory -> Bool)
-> (ErrorCategory -> ErrorCategory -> Bool) -> Eq ErrorCategory
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ErrorCategory -> ErrorCategory -> Bool
== :: ErrorCategory -> ErrorCategory -> Bool
$c/= :: ErrorCategory -> ErrorCategory -> Bool
/= :: ErrorCategory -> ErrorCategory -> Bool
Eq, Int -> ErrorCategory -> ShowS
[ErrorCategory] -> ShowS
ErrorCategory -> String
(Int -> ErrorCategory -> ShowS)
-> (ErrorCategory -> String)
-> ([ErrorCategory] -> ShowS)
-> Show ErrorCategory
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ErrorCategory -> ShowS
showsPrec :: Int -> ErrorCategory -> ShowS
$cshow :: ErrorCategory -> String
show :: ErrorCategory -> String
$cshowList :: [ErrorCategory] -> ShowS
showList :: [ErrorCategory] -> ShowS
Show, (forall x. ErrorCategory -> Rep ErrorCategory x)
-> (forall x. Rep ErrorCategory x -> ErrorCategory)
-> Generic ErrorCategory
forall x. Rep ErrorCategory x -> ErrorCategory
forall x. ErrorCategory -> Rep ErrorCategory x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ErrorCategory -> Rep ErrorCategory x
from :: forall x. ErrorCategory -> Rep ErrorCategory x
$cto :: forall x. Rep ErrorCategory x -> ErrorCategory
to :: forall x. Rep ErrorCategory x -> ErrorCategory
Generic, [ErrorCategory] -> Value
[ErrorCategory] -> Encoding
ErrorCategory -> Bool
ErrorCategory -> Value
ErrorCategory -> Encoding
(ErrorCategory -> Value)
-> (ErrorCategory -> Encoding)
-> ([ErrorCategory] -> Value)
-> ([ErrorCategory] -> Encoding)
-> (ErrorCategory -> Bool)
-> ToJSON ErrorCategory
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
$ctoJSON :: ErrorCategory -> Value
toJSON :: ErrorCategory -> Value
$ctoEncoding :: ErrorCategory -> Encoding
toEncoding :: ErrorCategory -> Encoding
$ctoJSONList :: [ErrorCategory] -> Value
toJSONList :: [ErrorCategory] -> Value
$ctoEncodingList :: [ErrorCategory] -> Encoding
toEncodingList :: [ErrorCategory] -> Encoding
$comitField :: ErrorCategory -> Bool
omitField :: ErrorCategory -> Bool
ToJSON, Maybe ErrorCategory
Value -> Parser [ErrorCategory]
Value -> Parser ErrorCategory
(Value -> Parser ErrorCategory)
-> (Value -> Parser [ErrorCategory])
-> Maybe ErrorCategory
-> FromJSON ErrorCategory
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser ErrorCategory
parseJSON :: Value -> Parser ErrorCategory
$cparseJSONList :: Value -> Parser [ErrorCategory]
parseJSONList :: Value -> Parser [ErrorCategory]
$comittedField :: Maybe ErrorCategory
omittedField :: Maybe ErrorCategory
FromJSON)

-- | Additional context information for errors
data ErrorContext = ErrorContext
  { ErrorContext -> Maybe Text
contextComponent :: Maybe Text
  -- ^ Component where error occurred
  , ErrorContext -> Maybe Text
contextOperation :: Maybe Text
  -- ^ Operation being performed
  , ErrorContext -> Maybe Text
contextInput :: Maybe Text
  -- ^ Input that caused the error
  , ErrorContext -> [(Text, Text)]
contextMetadata :: [(Text, Text)]
  -- ^ Additional metadata
  , ErrorContext -> UTCTime
contextTimestamp :: UTCTime
  -- ^ When the error occurred
  }
  deriving (ErrorContext -> ErrorContext -> Bool
(ErrorContext -> ErrorContext -> Bool)
-> (ErrorContext -> ErrorContext -> Bool) -> Eq ErrorContext
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ErrorContext -> ErrorContext -> Bool
== :: ErrorContext -> ErrorContext -> Bool
$c/= :: ErrorContext -> ErrorContext -> Bool
/= :: ErrorContext -> ErrorContext -> Bool
Eq, Int -> ErrorContext -> ShowS
[ErrorContext] -> ShowS
ErrorContext -> String
(Int -> ErrorContext -> ShowS)
-> (ErrorContext -> String)
-> ([ErrorContext] -> ShowS)
-> Show ErrorContext
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ErrorContext -> ShowS
showsPrec :: Int -> ErrorContext -> ShowS
$cshow :: ErrorContext -> String
show :: ErrorContext -> String
$cshowList :: [ErrorContext] -> ShowS
showList :: [ErrorContext] -> ShowS
Show, (forall x. ErrorContext -> Rep ErrorContext x)
-> (forall x. Rep ErrorContext x -> ErrorContext)
-> Generic ErrorContext
forall x. Rep ErrorContext x -> ErrorContext
forall x. ErrorContext -> Rep ErrorContext x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ErrorContext -> Rep ErrorContext x
from :: forall x. ErrorContext -> Rep ErrorContext x
$cto :: forall x. Rep ErrorContext x -> ErrorContext
to :: forall x. Rep ErrorContext x -> ErrorContext
Generic, [ErrorContext] -> Value
[ErrorContext] -> Encoding
ErrorContext -> Bool
ErrorContext -> Value
ErrorContext -> Encoding
(ErrorContext -> Value)
-> (ErrorContext -> Encoding)
-> ([ErrorContext] -> Value)
-> ([ErrorContext] -> Encoding)
-> (ErrorContext -> Bool)
-> ToJSON ErrorContext
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
$ctoJSON :: ErrorContext -> Value
toJSON :: ErrorContext -> Value
$ctoEncoding :: ErrorContext -> Encoding
toEncoding :: ErrorContext -> Encoding
$ctoJSONList :: [ErrorContext] -> Value
toJSONList :: [ErrorContext] -> Value
$ctoEncodingList :: [ErrorContext] -> Encoding
toEncodingList :: [ErrorContext] -> Encoding
$comitField :: ErrorContext -> Bool
omitField :: ErrorContext -> Bool
ToJSON, Maybe ErrorContext
Value -> Parser [ErrorContext]
Value -> Parser ErrorContext
(Value -> Parser ErrorContext)
-> (Value -> Parser [ErrorContext])
-> Maybe ErrorContext
-> FromJSON ErrorContext
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser ErrorContext
parseJSON :: Value -> Parser ErrorContext
$cparseJSONList :: Value -> Parser [ErrorContext]
parseJSONList :: Value -> Parser [ErrorContext]
$comittedField :: Maybe ErrorContext
omittedField :: Maybe ErrorContext
FromJSON)

-- | The central error type for langchain-hs
data LangchainError = LangchainError
  { LangchainError -> Text
errorMessage :: Text
  -- ^ Human-readable error message
  , LangchainError -> ErrorSeverity
errorSeverity :: ErrorSeverity
  -- ^ Severity level
  , LangchainError -> ErrorCategory
errorCategory :: ErrorCategory
  -- ^ Error category
  , LangchainError -> Maybe ErrorContext
errorContext :: Maybe ErrorContext
  -- ^ Additional context
  , LangchainError -> Maybe LangchainError
errorCause :: Maybe LangchainError
  -- ^ Chained/nested error
  , LangchainError -> Maybe Text
errorCode :: Maybe Text
  -- ^ Optional error code
  }
  deriving (LangchainError -> LangchainError -> Bool
(LangchainError -> LangchainError -> Bool)
-> (LangchainError -> LangchainError -> Bool) -> Eq LangchainError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: LangchainError -> LangchainError -> Bool
== :: LangchainError -> LangchainError -> Bool
$c/= :: LangchainError -> LangchainError -> Bool
/= :: LangchainError -> LangchainError -> Bool
Eq, Int -> LangchainError -> ShowS
[LangchainError] -> ShowS
LangchainError -> String
(Int -> LangchainError -> ShowS)
-> (LangchainError -> String)
-> ([LangchainError] -> ShowS)
-> Show LangchainError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> LangchainError -> ShowS
showsPrec :: Int -> LangchainError -> ShowS
$cshow :: LangchainError -> String
show :: LangchainError -> String
$cshowList :: [LangchainError] -> ShowS
showList :: [LangchainError] -> ShowS
Show, (forall x. LangchainError -> Rep LangchainError x)
-> (forall x. Rep LangchainError x -> LangchainError)
-> Generic LangchainError
forall x. Rep LangchainError x -> LangchainError
forall x. LangchainError -> Rep LangchainError x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. LangchainError -> Rep LangchainError x
from :: forall x. LangchainError -> Rep LangchainError x
$cto :: forall x. Rep LangchainError x -> LangchainError
to :: forall x. Rep LangchainError x -> LangchainError
Generic, [LangchainError] -> Value
[LangchainError] -> Encoding
LangchainError -> Bool
LangchainError -> Value
LangchainError -> Encoding
(LangchainError -> Value)
-> (LangchainError -> Encoding)
-> ([LangchainError] -> Value)
-> ([LangchainError] -> Encoding)
-> (LangchainError -> Bool)
-> ToJSON LangchainError
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
$ctoJSON :: LangchainError -> Value
toJSON :: LangchainError -> Value
$ctoEncoding :: LangchainError -> Encoding
toEncoding :: LangchainError -> Encoding
$ctoJSONList :: [LangchainError] -> Value
toJSONList :: [LangchainError] -> Value
$ctoEncodingList :: [LangchainError] -> Encoding
toEncodingList :: [LangchainError] -> Encoding
$comitField :: LangchainError -> Bool
omitField :: LangchainError -> Bool
ToJSON, Maybe LangchainError
Value -> Parser [LangchainError]
Value -> Parser LangchainError
(Value -> Parser LangchainError)
-> (Value -> Parser [LangchainError])
-> Maybe LangchainError
-> FromJSON LangchainError
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser LangchainError
parseJSON :: Value -> Parser LangchainError
$cparseJSONList :: Value -> Parser [LangchainError]
parseJSONList :: Value -> Parser [LangchainError]
$comittedField :: Maybe LangchainError
omittedField :: Maybe LangchainError
FromJSON)

instance Exception LangchainError where
  displayException :: LangchainError -> String
displayException LangchainError {Maybe Text
Maybe LangchainError
Maybe ErrorContext
Text
ErrorCategory
ErrorSeverity
errorMessage :: LangchainError -> Text
errorSeverity :: LangchainError -> ErrorSeverity
errorCategory :: LangchainError -> ErrorCategory
errorContext :: LangchainError -> Maybe ErrorContext
errorCause :: LangchainError -> Maybe LangchainError
errorCode :: LangchainError -> Maybe Text
errorMessage :: Text
errorSeverity :: ErrorSeverity
errorCategory :: ErrorCategory
errorContext :: Maybe ErrorContext
errorCause :: Maybe LangchainError
errorCode :: Maybe Text
..} =
    Text -> String
T.unpack (Text -> String) -> Text -> String
forall a b. (a -> b) -> a -> b
$
      [Text] -> Text
T.unlines ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$
        (Text -> Bool) -> [Text] -> [Text]
forall a. (a -> Bool) -> [a] -> [a]
filter
          (Bool -> Bool
not (Bool -> Bool) -> (Text -> Bool) -> Text -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Bool
T.null)
          [ Text
"["
              Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (ErrorSeverity -> String
forall a. Show a => a -> String
show ErrorSeverity
errorSeverity)
              Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"] "
              Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (ErrorCategory -> String
forall a. Show a => a -> String
show ErrorCategory
errorCategory)
              Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
": "
              Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
errorMessage
          , Text -> (Text -> Text) -> Maybe Text -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" (Text
"Error Code: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>) Maybe Text
errorCode
          , Text -> (ErrorContext -> Text) -> Maybe ErrorContext -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" ErrorContext -> Text
formatContext Maybe ErrorContext
errorContext
          , Text -> (LangchainError -> Text) -> Maybe LangchainError -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" (\LangchainError
cause -> Text
"Caused by: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (LangchainError -> String
forall a. Show a => a -> String
show LangchainError
cause)) Maybe LangchainError
errorCause
          ]
    where
      formatContext :: ErrorContext -> Text
formatContext ErrorContext {[(Text, Text)]
Maybe Text
UTCTime
contextComponent :: ErrorContext -> Maybe Text
contextOperation :: ErrorContext -> Maybe Text
contextInput :: ErrorContext -> Maybe Text
contextMetadata :: ErrorContext -> [(Text, Text)]
contextTimestamp :: ErrorContext -> UTCTime
contextComponent :: Maybe Text
contextOperation :: Maybe Text
contextInput :: Maybe Text
contextMetadata :: [(Text, Text)]
contextTimestamp :: UTCTime
..} =
        [Text] -> Text
T.unlines ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$
          (Text -> Bool) -> [Text] -> [Text]
forall a. (a -> Bool) -> [a] -> [a]
filter
            (Bool -> Bool
not (Bool -> Bool) -> (Text -> Bool) -> Text -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Bool
T.null)
            [ Text -> (Text -> Text) -> Maybe Text -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" (Text
"Component: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>) Maybe Text
contextComponent
            , Text -> (Text -> Text) -> Maybe Text -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" (Text
"Operation: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>) Maybe Text
contextOperation
            , Text -> (Text -> Text) -> Maybe Text -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" (Text
"Input: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>) Maybe Text
contextInput
            , if [(Text, Text)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Text, Text)]
contextMetadata then Text
"" else Text
"Metadata: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack ([(Text, Text)] -> String
forall a. Show a => a -> String
show [(Text, Text)]
contextMetadata)
            , Text
"Timestamp: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (UTCTime -> String
forall a. Show a => a -> String
show UTCTime
contextTimestamp)
            ]

-- | Type alias for results that can fail with LangchainError
type LangchainResult a = Either LangchainError a

-- | Type alias for IO operations that can fail with LangchainError
type LangchainIO a = IO (LangchainResult a)

-- | Create an LLM-related error
llmError :: Text -> Maybe Text -> Maybe Text -> LangchainError
llmError :: Text -> Maybe Text -> Maybe Text -> LangchainError
llmError Text
msg Maybe Text
_model Maybe Text
_operation =
  LangchainError
    { errorMessage :: Text
errorMessage = Text
msg
    , errorSeverity :: ErrorSeverity
errorSeverity = ErrorSeverity
High
    , errorCategory :: ErrorCategory
errorCategory = ErrorCategory
LLMError
    , errorContext :: Maybe ErrorContext
errorContext = Maybe ErrorContext
forall a. Maybe a
Nothing
    , errorCause :: Maybe LangchainError
errorCause = Maybe LangchainError
forall a. Maybe a
Nothing
    , errorCode :: Maybe Text
errorCode = Maybe Text
forall a. Maybe a
Nothing
    }

-- | Create an LLM error with context
llmErrorWithContext ::
  Text ->
  Maybe Text ->
  Maybe Text ->
  ErrorContext ->
  LangchainError
llmErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
llmErrorWithContext Text
msg Maybe Text
model Maybe Text
operation ErrorContext
ctx =
  (Text -> Maybe Text -> Maybe Text -> LangchainError
llmError Text
msg Maybe Text
model Maybe Text
operation)
    { errorContext =
        Just ctx {contextComponent = model, contextOperation = operation}
    }

-- | Create an agent-related error
agentError :: Text -> Maybe Text -> Maybe Text -> LangchainError
agentError :: Text -> Maybe Text -> Maybe Text -> LangchainError
agentError Text
msg Maybe Text
_agentType Maybe Text
_operation =
  LangchainError
    { errorMessage :: Text
errorMessage = Text
msg
    , errorSeverity :: ErrorSeverity
errorSeverity = ErrorSeverity
High
    , errorCategory :: ErrorCategory
errorCategory = ErrorCategory
AgentError
    , errorContext :: Maybe ErrorContext
errorContext = Maybe ErrorContext
forall a. Maybe a
Nothing
    , errorCause :: Maybe LangchainError
errorCause = Maybe LangchainError
forall a. Maybe a
Nothing
    , errorCode :: Maybe Text
errorCode = Maybe Text
forall a. Maybe a
Nothing
    }

-- | Create an agent error with context
agentErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
agentErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
agentErrorWithContext Text
msg Maybe Text
agentType Maybe Text
operation ErrorContext
ctx =
  (Text -> Maybe Text -> Maybe Text -> LangchainError
agentError Text
msg Maybe Text
agentType Maybe Text
operation)
    { errorContext = Just ctx {contextComponent = agentType, contextOperation = operation}
    }

-- | Create a memory-related error
memoryError :: Text -> Maybe Text -> Maybe Text -> LangchainError
memoryError :: Text -> Maybe Text -> Maybe Text -> LangchainError
memoryError Text
msg Maybe Text
_memoryType Maybe Text
_operation =
  LangchainError
    { errorMessage :: Text
errorMessage = Text
msg
    , errorSeverity :: ErrorSeverity
errorSeverity = ErrorSeverity
Medium
    , errorCategory :: ErrorCategory
errorCategory = ErrorCategory
MemoryError
    , errorContext :: Maybe ErrorContext
errorContext = Maybe ErrorContext
forall a. Maybe a
Nothing
    , errorCause :: Maybe LangchainError
errorCause = Maybe LangchainError
forall a. Maybe a
Nothing
    , errorCode :: Maybe Text
errorCode = Maybe Text
forall a. Maybe a
Nothing
    }

-- | Create a memory error with context
memoryErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
memoryErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
memoryErrorWithContext Text
msg Maybe Text
memoryType Maybe Text
operation ErrorContext
ctx =
  (Text -> Maybe Text -> Maybe Text -> LangchainError
memoryError Text
msg Maybe Text
memoryType Maybe Text
operation)
    { errorContext = Just ctx {contextComponent = memoryType, contextOperation = operation}
    }

-- | Create a tool-related error
toolError :: Text -> Maybe Text -> Maybe Text -> LangchainError
toolError :: Text -> Maybe Text -> Maybe Text -> LangchainError
toolError Text
msg Maybe Text
_toolName Maybe Text
_operation =
  LangchainError
    { errorMessage :: Text
errorMessage = Text
msg
    , errorSeverity :: ErrorSeverity
errorSeverity = ErrorSeverity
High
    , errorCategory :: ErrorCategory
errorCategory = ErrorCategory
ToolError
    , errorContext :: Maybe ErrorContext
errorContext = Maybe ErrorContext
forall a. Maybe a
Nothing
    , errorCause :: Maybe LangchainError
errorCause = Maybe LangchainError
forall a. Maybe a
Nothing
    , errorCode :: Maybe Text
errorCode = Maybe Text
forall a. Maybe a
Nothing
    }

-- | Create a tool error with context
toolErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
toolErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
toolErrorWithContext Text
msg Maybe Text
toolName Maybe Text
operation ErrorContext
ctx =
  (Text -> Maybe Text -> Maybe Text -> LangchainError
toolError Text
msg Maybe Text
toolName Maybe Text
operation)
    { errorContext = Just ctx {contextComponent = toolName, contextOperation = operation}
    }

-- | Create a vector store error
vectorStoreError :: Text -> Maybe Text -> Maybe Text -> LangchainError
vectorStoreError :: Text -> Maybe Text -> Maybe Text -> LangchainError
vectorStoreError Text
msg Maybe Text
_storeType Maybe Text
_operation =
  LangchainError
    { errorMessage :: Text
errorMessage = Text
msg
    , errorSeverity :: ErrorSeverity
errorSeverity = ErrorSeverity
High
    , errorCategory :: ErrorCategory
errorCategory = ErrorCategory
VectorStoreError
    , errorContext :: Maybe ErrorContext
errorContext = Maybe ErrorContext
forall a. Maybe a
Nothing
    , errorCause :: Maybe LangchainError
errorCause = Maybe LangchainError
forall a. Maybe a
Nothing
    , errorCode :: Maybe Text
errorCode = Maybe Text
forall a. Maybe a
Nothing
    }

-- | Create a vector store error with context
vectorStoreErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
vectorStoreErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
vectorStoreErrorWithContext Text
msg Maybe Text
storeType Maybe Text
operation ErrorContext
ctx =
  (Text -> Maybe Text -> Maybe Text -> LangchainError
vectorStoreError Text
msg Maybe Text
storeType Maybe Text
operation)
    { errorContext = Just ctx {contextComponent = storeType, contextOperation = operation}
    }

-- | Create a document loader error
documentLoaderError :: Text -> Maybe Text -> Maybe Text -> LangchainError
documentLoaderError :: Text -> Maybe Text -> Maybe Text -> LangchainError
documentLoaderError Text
msg Maybe Text
_loaderType Maybe Text
_operation =
  LangchainError
    { errorMessage :: Text
errorMessage = Text
msg
    , errorSeverity :: ErrorSeverity
errorSeverity = ErrorSeverity
Medium
    , errorCategory :: ErrorCategory
errorCategory = ErrorCategory
DocumentLoaderError
    , errorContext :: Maybe ErrorContext
errorContext = Maybe ErrorContext
forall a. Maybe a
Nothing
    , errorCause :: Maybe LangchainError
errorCause = Maybe LangchainError
forall a. Maybe a
Nothing
    , errorCode :: Maybe Text
errorCode = Maybe Text
forall a. Maybe a
Nothing
    }

-- | Create a document loader error with context
documentLoaderErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
documentLoaderErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
documentLoaderErrorWithContext Text
msg Maybe Text
loaderType Maybe Text
operation ErrorContext
ctx =
  (Text -> Maybe Text -> Maybe Text -> LangchainError
documentLoaderError Text
msg Maybe Text
loaderType Maybe Text
operation)
    { errorContext = Just ctx {contextComponent = loaderType, contextOperation = operation}
    }

-- | Create an embedding error
embeddingError :: Text -> Maybe Text -> Maybe Text -> LangchainError
embeddingError :: Text -> Maybe Text -> Maybe Text -> LangchainError
embeddingError Text
msg Maybe Text
_embeddingType Maybe Text
_operation =
  LangchainError
    { errorMessage :: Text
errorMessage = Text
msg
    , errorSeverity :: ErrorSeverity
errorSeverity = ErrorSeverity
High
    , errorCategory :: ErrorCategory
errorCategory = ErrorCategory
EmbeddingError
    , errorContext :: Maybe ErrorContext
errorContext = Maybe ErrorContext
forall a. Maybe a
Nothing
    , errorCause :: Maybe LangchainError
errorCause = Maybe LangchainError
forall a. Maybe a
Nothing
    , errorCode :: Maybe Text
errorCode = Maybe Text
forall a. Maybe a
Nothing
    }

-- | Create an embedding error with context
embeddingErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
embeddingErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
embeddingErrorWithContext Text
msg Maybe Text
embeddingType Maybe Text
operation ErrorContext
ctx =
  (Text -> Maybe Text -> Maybe Text -> LangchainError
embeddingError Text
msg Maybe Text
embeddingType Maybe Text
operation)
    { errorContext = Just ctx {contextComponent = embeddingType, contextOperation = operation}
    }

-- | Create a runnable error
runnableError :: Text -> Maybe Text -> Maybe Text -> LangchainError
runnableError :: Text -> Maybe Text -> Maybe Text -> LangchainError
runnableError Text
msg Maybe Text
_runnableType Maybe Text
_operation =
  LangchainError
    { errorMessage :: Text
errorMessage = Text
msg
    , errorSeverity :: ErrorSeverity
errorSeverity = ErrorSeverity
High
    , errorCategory :: ErrorCategory
errorCategory = ErrorCategory
RunnableError
    , errorContext :: Maybe ErrorContext
errorContext = Maybe ErrorContext
forall a. Maybe a
Nothing
    , errorCause :: Maybe LangchainError
errorCause = Maybe LangchainError
forall a. Maybe a
Nothing
    , errorCode :: Maybe Text
errorCode = Maybe Text
forall a. Maybe a
Nothing
    }

-- | Create a runnable error with context
runnableErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
runnableErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
runnableErrorWithContext Text
msg Maybe Text
runnableType Maybe Text
operation ErrorContext
ctx =
  (Text -> Maybe Text -> Maybe Text -> LangchainError
runnableError Text
msg Maybe Text
runnableType Maybe Text
operation)
    { errorContext = Just ctx {contextComponent = runnableType, contextOperation = operation}
    }

-- | Create a parsing error
parsingError :: Text -> Maybe Text -> Maybe Text -> LangchainError
parsingError :: Text -> Maybe Text -> Maybe Text -> LangchainError
parsingError Text
msg Maybe Text
_parserType Maybe Text
_input =
  LangchainError
    { errorMessage :: Text
errorMessage = Text
msg Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
"" Maybe Text
_parserType
    , errorSeverity :: ErrorSeverity
errorSeverity = ErrorSeverity
Medium
    , errorCategory :: ErrorCategory
errorCategory = ErrorCategory
ParsingError
    , errorContext :: Maybe ErrorContext
errorContext = Maybe ErrorContext
forall a. Maybe a
Nothing
    , errorCause :: Maybe LangchainError
errorCause = Maybe LangchainError
forall a. Maybe a
Nothing
    , errorCode :: Maybe Text
errorCode = Maybe Text
_input
    }

-- | Create a parsing error with context
parsingErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
parsingErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
parsingErrorWithContext Text
msg Maybe Text
parserType Maybe Text
input ErrorContext
ctx =
  (Text -> Maybe Text -> Maybe Text -> LangchainError
parsingError Text
msg Maybe Text
parserType Maybe Text
input)
    { errorContext = Just ctx {contextComponent = parserType, contextInput = input}
    }

-- | Create a network error
networkError :: Text -> Maybe Text -> Maybe Text -> LangchainError
networkError :: Text -> Maybe Text -> Maybe Text -> LangchainError
networkError Text
msg Maybe Text
_endpoint Maybe Text
_operation =
  LangchainError
    { errorMessage :: Text
errorMessage = Text
msg
    , errorSeverity :: ErrorSeverity
errorSeverity = ErrorSeverity
High
    , errorCategory :: ErrorCategory
errorCategory = ErrorCategory
NetworkError
    , errorContext :: Maybe ErrorContext
errorContext = Maybe ErrorContext
forall a. Maybe a
Nothing
    , errorCause :: Maybe LangchainError
errorCause = Maybe LangchainError
forall a. Maybe a
Nothing
    , errorCode :: Maybe Text
errorCode = Maybe Text
forall a. Maybe a
Nothing
    }

-- | Create a network error with context
networkErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
networkErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
networkErrorWithContext Text
msg Maybe Text
endpoint Maybe Text
operation ErrorContext
ctx =
  (Text -> Maybe Text -> Maybe Text -> LangchainError
networkError Text
msg Maybe Text
endpoint Maybe Text
operation)
    { errorContext = Just ctx {contextComponent = endpoint, contextOperation = operation}
    }

-- | Create a configuration error
configurationError :: Text -> Maybe Text -> Maybe Text -> LangchainError
configurationError :: Text -> Maybe Text -> Maybe Text -> LangchainError
configurationError Text
msg Maybe Text
_configKey Maybe Text
_operation =
  LangchainError
    { errorMessage :: Text
errorMessage = Text
msg
    , errorSeverity :: ErrorSeverity
errorSeverity = ErrorSeverity
Critical
    , errorCategory :: ErrorCategory
errorCategory = ErrorCategory
ConfigurationError
    , errorContext :: Maybe ErrorContext
errorContext = Maybe ErrorContext
forall a. Maybe a
Nothing
    , errorCause :: Maybe LangchainError
errorCause = Maybe LangchainError
forall a. Maybe a
Nothing
    , errorCode :: Maybe Text
errorCode = Maybe Text
forall a. Maybe a
Nothing
    }

-- | Create a configuration error with context
configurationErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
configurationErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
configurationErrorWithContext Text
msg Maybe Text
configKey Maybe Text
operation ErrorContext
ctx =
  (Text -> Maybe Text -> Maybe Text -> LangchainError
configurationError Text
msg Maybe Text
configKey Maybe Text
operation)
    { errorContext = Just ctx {contextComponent = configKey, contextOperation = operation}
    }

-- | Create a validation error
validationError :: Text -> Maybe Text -> Maybe Text -> LangchainError
validationError :: Text -> Maybe Text -> Maybe Text -> LangchainError
validationError Text
msg Maybe Text
_field Maybe Text
_input =
  LangchainError
    { errorMessage :: Text
errorMessage = Text
msg
    , errorSeverity :: ErrorSeverity
errorSeverity = ErrorSeverity
Medium
    , errorCategory :: ErrorCategory
errorCategory = ErrorCategory
ValidationError
    , errorContext :: Maybe ErrorContext
errorContext = Maybe ErrorContext
forall a. Maybe a
Nothing
    , errorCause :: Maybe LangchainError
errorCause = Maybe LangchainError
forall a. Maybe a
Nothing
    , errorCode :: Maybe Text
errorCode = Maybe Text
forall a. Maybe a
Nothing
    }

-- | Create a validation error with context
validationErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
validationErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
validationErrorWithContext Text
msg Maybe Text
field Maybe Text
input ErrorContext
ctx =
  (Text -> Maybe Text -> Maybe Text -> LangchainError
validationError Text
msg Maybe Text
field Maybe Text
input)
    { errorContext = Just ctx {contextComponent = field, contextInput = input}
    }

-- | Create an internal error
internalError :: Text -> Maybe Text -> Maybe Text -> LangchainError
internalError :: Text -> Maybe Text -> Maybe Text -> LangchainError
internalError Text
msg Maybe Text
_component Maybe Text
_operation =
  LangchainError
    { errorMessage :: Text
errorMessage = Text
msg
    , errorSeverity :: ErrorSeverity
errorSeverity = ErrorSeverity
Critical
    , errorCategory :: ErrorCategory
errorCategory = ErrorCategory
InternalError
    , errorContext :: Maybe ErrorContext
errorContext = Maybe ErrorContext
forall a. Maybe a
Nothing
    , errorCause :: Maybe LangchainError
errorCause = Maybe LangchainError
forall a. Maybe a
Nothing
    , errorCode :: Maybe Text
errorCode = Maybe Text
forall a. Maybe a
Nothing
    }

-- | Create an internal error with context
internalErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
internalErrorWithContext :: Text -> Maybe Text -> Maybe Text -> ErrorContext -> LangchainError
internalErrorWithContext Text
msg Maybe Text
component Maybe Text
operation ErrorContext
ctx =
  (Text -> Maybe Text -> Maybe Text -> LangchainError
internalError Text
msg Maybe Text
component Maybe Text
operation)
    { errorContext = Just ctx {contextComponent = component, contextOperation = operation}
    }

-- | Chain an error with a new message, preserving the original as the cause
chainError :: Text -> LangchainError -> LangchainError
chainError :: Text -> LangchainError -> LangchainError
chainError Text
msg LangchainError
originalError =
  LangchainError
    { errorMessage :: Text
errorMessage = Text
msg
    , errorSeverity :: ErrorSeverity
errorSeverity = LangchainError -> ErrorSeverity
errorSeverity LangchainError
originalError
    , errorCategory :: ErrorCategory
errorCategory = LangchainError -> ErrorCategory
errorCategory LangchainError
originalError
    , errorContext :: Maybe ErrorContext
errorContext = LangchainError -> Maybe ErrorContext
errorContext LangchainError
originalError
    , errorCause :: Maybe LangchainError
errorCause = LangchainError -> Maybe LangchainError
forall a. a -> Maybe a
Just LangchainError
originalError
    , errorCode :: Maybe Text
errorCode = LangchainError -> Maybe Text
errorCode LangchainError
originalError
    }

-- | Add context to an existing error
addContext :: ErrorContext -> LangchainError -> LangchainError
addContext :: ErrorContext -> LangchainError -> LangchainError
addContext ErrorContext
ctx LangchainError
err = LangchainError
err {errorContext = Just ctx}

-- | Execute an action with error context, automatically adding context to any errors
withErrorContext :: MonadIO m => ErrorContext -> LangchainIO a -> m (LangchainResult a)
withErrorContext :: forall (m :: * -> *) a.
MonadIO m =>
ErrorContext -> LangchainIO a -> m (LangchainResult a)
withErrorContext ErrorContext
ctx LangchainIO a
action = LangchainIO a -> m (LangchainResult a)
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (LangchainIO a -> m (LangchainResult a))
-> LangchainIO a -> m (LangchainResult a)
forall a b. (a -> b) -> a -> b
$ do
  result <- LangchainIO a
action
  case result of
    Left LangchainError
err -> LangchainResult a -> LangchainIO a
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (LangchainResult a -> LangchainIO a)
-> LangchainResult a -> LangchainIO a
forall a b. (a -> b) -> a -> b
$ LangchainError -> LangchainResult a
forall a b. a -> Either a b
Left (LangchainError -> LangchainResult a)
-> LangchainError -> LangchainResult a
forall a b. (a -> b) -> a -> b
$ ErrorContext -> LangchainError -> LangchainError
addContext ErrorContext
ctx LangchainError
err
    Right a
val -> LangchainResult a -> LangchainIO a
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (LangchainResult a -> LangchainIO a)
-> LangchainResult a -> LangchainIO a
forall a b. (a -> b) -> a -> b
$ a -> LangchainResult a
forall a b. b -> Either a b
Right a
val

-- | Map a function over the error in a result
mapError :: (LangchainError -> LangchainError) -> LangchainResult a -> LangchainResult a
mapError :: forall a.
(LangchainError -> LangchainError)
-> LangchainResult a -> LangchainResult a
mapError LangchainError -> LangchainError
f (Left LangchainError
err) = LangchainError -> Either LangchainError a
forall a b. a -> Either a b
Left (LangchainError -> LangchainError
f LangchainError
err)
mapError LangchainError -> LangchainError
_ (Right a
val) = a -> Either LangchainError a
forall a b. b -> Either a b
Right a
val

-- | Convert a String to LangchainError
fromString :: String -> LangchainError
fromString :: String -> LangchainError
fromString String
str = Text -> Maybe Text -> Maybe Text -> LangchainError
internalError (String -> Text
T.pack String
str) Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing

-- | Convert LangchainError to String
toString :: LangchainError -> String
toString :: LangchainError -> String
toString = LangchainError -> String
forall e. Exception e => e -> String
displayException

-- | Convert LangchainError to Text
toText :: LangchainError -> Text
toText :: LangchainError -> Text
toText = String -> Text
T.pack (String -> Text)
-> (LangchainError -> String) -> LangchainError -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LangchainError -> String
toString

-- | Log an error to stderr (can be extended to use proper logging)
logError :: MonadIO m => LangchainError -> m ()
logError :: forall (m :: * -> *). MonadIO m => LangchainError -> m ()
logError LangchainError
err = IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ Handle -> String -> IO ()
hPutStrLn Handle
stderr (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ LangchainError -> String
toString LangchainError
err

-- | Check if an error is retryable based on its category and severity
isRetryable :: LangchainError -> Bool
isRetryable :: LangchainError -> Bool
isRetryable LangchainError {Maybe Text
Maybe LangchainError
Maybe ErrorContext
Text
ErrorCategory
ErrorSeverity
errorMessage :: LangchainError -> Text
errorSeverity :: LangchainError -> ErrorSeverity
errorCategory :: LangchainError -> ErrorCategory
errorContext :: LangchainError -> Maybe ErrorContext
errorCause :: LangchainError -> Maybe LangchainError
errorCode :: LangchainError -> Maybe Text
errorMessage :: Text
errorSeverity :: ErrorSeverity
errorCategory :: ErrorCategory
errorContext :: Maybe ErrorContext
errorCause :: Maybe LangchainError
errorCode :: Maybe Text
..} = case ErrorCategory
errorCategory of
  ErrorCategory
NetworkError -> ErrorSeverity
errorSeverity ErrorSeverity -> ErrorSeverity -> Bool
forall a. Ord a => a -> a -> Bool
<= ErrorSeverity
High
  ErrorCategory
LLMError -> ErrorSeverity
errorSeverity ErrorSeverity -> ErrorSeverity -> Bool
forall a. Ord a => a -> a -> Bool
<= ErrorSeverity
Medium
  ErrorCategory
VectorStoreError -> ErrorSeverity
errorSeverity ErrorSeverity -> ErrorSeverity -> Bool
forall a. Ord a => a -> a -> Bool
<= ErrorSeverity
Medium
  ErrorCategory
EmbeddingError -> ErrorSeverity
errorSeverity ErrorSeverity -> ErrorSeverity -> Bool
forall a. Ord a => a -> a -> Bool
<= ErrorSeverity
Medium
  ErrorCategory
ToolError -> ErrorSeverity
errorSeverity ErrorSeverity -> ErrorSeverity -> Bool
forall a. Ord a => a -> a -> Bool
<= ErrorSeverity
Medium
  ErrorCategory
_ -> Bool
False

-- | Get the severity of an error
getSeverity :: LangchainError -> ErrorSeverity
getSeverity :: LangchainError -> ErrorSeverity
getSeverity = LangchainError -> ErrorSeverity
errorSeverity

-- | Get the category of an error
getCategory :: LangchainError -> ErrorCategory
getCategory :: LangchainError -> ErrorCategory
getCategory = LangchainError -> ErrorCategory
errorCategory

-- | Convert a String error to LangchainError (for backward compatibility)
fromStringError :: String -> LangchainError
fromStringError :: String -> LangchainError
fromStringError = String -> LangchainError
fromString

-- | Convert an IO exception to LangchainError
fromException :: SomeException -> LangchainError
fromException :: SomeException -> LangchainError
fromException SomeException
ex = Text -> Maybe Text -> Maybe Text -> LangchainError
internalError (String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ SomeException -> String
forall e. Exception e => e -> String
displayException SomeException
ex) Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing

-- | Lift an Either String to LangchainResult
liftStringError :: Either String a -> LangchainResult a
liftStringError :: forall a. Either String a -> LangchainResult a
liftStringError (Left String
err) = LangchainError -> Either LangchainError a
forall a b. a -> Either a b
Left (String -> LangchainError
fromString String
err)
liftStringError (Right a
val) = a -> Either LangchainError a
forall a b. b -> Either a b
Right a
val

-- | Create a simple error with just a message (uses InternalError category)
simpleError :: Text -> LangchainError
simpleError :: Text -> LangchainError
simpleError Text
msg = Text -> Maybe Text -> Maybe Text -> LangchainError
internalError Text
msg Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing

-- | Catch IO exceptions and convert them to LangchainError
catchToLangchainError :: IO a -> IO (LangchainResult a)
catchToLangchainError :: forall a. IO a -> IO (LangchainResult a)
catchToLangchainError IO a
action = do
  result <- IO a -> IO (Either SomeException a)
forall e a. Exception e => IO a -> IO (Either e a)
try IO a
action
  case result of
    Left SomeException
ex -> LangchainResult a -> IO (LangchainResult a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (LangchainResult a -> IO (LangchainResult a))
-> LangchainResult a -> IO (LangchainResult a)
forall a b. (a -> b) -> a -> b
$ LangchainError -> LangchainResult a
forall a b. a -> Either a b
Left (LangchainError -> LangchainResult a)
-> LangchainError -> LangchainResult a
forall a b. (a -> b) -> a -> b
$ SomeException -> LangchainError
fromException SomeException
ex
    Right a
val -> LangchainResult a -> IO (LangchainResult a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (LangchainResult a -> IO (LangchainResult a))
-> LangchainResult a -> IO (LangchainResult a)
forall a b. (a -> b) -> a -> b
$ a -> LangchainResult a
forall a b. b -> Either a b
Right a
val

-- | Run an action and add context to any errors
withContext :: Text -> Text -> LangchainResult a -> LangchainResult a
withContext :: forall a. Text -> Text -> LangchainResult a -> LangchainResult a
withContext Text
component Text
operation LangchainResult a
result = case LangchainResult a
result of
  Left LangchainError
err ->
    case LangchainError -> Maybe ErrorContext
errorContext LangchainError
err of
      Just ErrorContext
ctx ->
        LangchainError -> LangchainResult a
forall a b. a -> Either a b
Left (LangchainError -> LangchainResult a)
-> LangchainError -> LangchainResult a
forall a b. (a -> b) -> a -> b
$
          LangchainError
err
            { errorContext =
                Just $
                  ErrorContext
                    { contextComponent = Just component
                    , contextOperation = Just operation
                    , contextInput = Nothing
                    , contextMetadata = []
                    , contextTimestamp = contextTimestamp ctx
                    }
            }
      Maybe ErrorContext
Nothing -> LangchainError -> LangchainResult a
forall a b. a -> Either a b
Left LangchainError
err
  Right a
val -> a -> LangchainResult a
forall a b. b -> Either a b
Right a
val

-- | Run an action and add context to any errors (IO version)
withContextIO :: MonadIO m => Text -> Text -> LangchainResult a -> m (LangchainResult a)
withContextIO :: forall (m :: * -> *) a.
MonadIO m =>
Text -> Text -> LangchainResult a -> m (LangchainResult a)
withContextIO Text
component Text
operation LangchainResult a
result = case LangchainResult a
result of
  Left LangchainError
err -> do
    now <- IO UTCTime -> m UTCTime
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO UTCTime
getCurrentTime
    return $
      Left $
        err
          { errorContext =
              Just $
                ErrorContext
                  { contextComponent = Just component
                  , contextOperation = Just operation
                  , contextInput = Nothing
                  , contextMetadata = []
                  , contextTimestamp = now
                  }
          }
  Right a
val -> LangchainResult a -> m (LangchainResult a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (LangchainResult a -> m (LangchainResult a))
-> LangchainResult a -> m (LangchainResult a)
forall a b. (a -> b) -> a -> b
$ a -> LangchainResult a
forall a b. b -> Either a b
Right a
val