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"