never executed always true always false
    1 module PureClaw.Tools.FileRead
    2   ( -- * Tool registration
    3     fileReadTool
    4   ) where
    5 
    6 import Control.Exception
    7 import Data.Aeson
    8 import Data.Aeson.Types
    9 import Data.ByteString qualified as BS
   10 import Data.Text (Text)
   11 import Data.Text qualified as T
   12 import Data.Text.Encoding qualified as TE
   13 
   14 import PureClaw.Core.Types
   15 import PureClaw.Handles.File
   16 import PureClaw.Providers.Class
   17 import PureClaw.Security.Path
   18 import PureClaw.Tools.Registry
   19 
   20 -- | Create a file read tool that reads files through SafePath validation.
   21 fileReadTool :: WorkspaceRoot -> FileHandle -> (ToolDefinition, ToolHandler)
   22 fileReadTool root fh = (def, handler)
   23   where
   24     def = ToolDefinition
   25       { _td_name        = "file_read"
   26       , _td_description = "Read the contents of a file within the workspace."
   27       , _td_inputSchema = object
   28           [ "type" .= ("object" :: Text)
   29           , "properties" .= object
   30               [ "path" .= object
   31                   [ "type" .= ("string" :: Text)
   32                   , "description" .= ("The file path relative to the workspace root" :: Text)
   33                   ]
   34               ]
   35           , "required" .= (["path"] :: [Text])
   36           ]
   37       }
   38 
   39     handler = ToolHandler $ \input ->
   40       case parseEither parseInput input of
   41         Left err -> pure (T.pack err, True)
   42         Right path -> do
   43           pathResult <- mkSafePath root (T.unpack path)
   44           case pathResult of
   45             Left pe -> pure (T.pack (show pe), True)
   46             Right sp -> do
   47               result <- try @SomeException (_fh_readFile fh sp)
   48               case result of
   49                 Left e -> pure (T.pack (show e), True)
   50                 Right bs -> case TE.decodeUtf8' bs of
   51                   Left _ -> pure ("Binary file (" <> T.pack (show (BS.length bs)) <> " bytes)", False)
   52                   Right txt -> pure (txt, False)
   53 
   54     parseInput :: Value -> Parser Text
   55     parseInput = withObject "FileReadInput" $ \o -> o .: "path"