never executed always true always false
    1 module PureClaw.Tools.Git
    2   ( -- * Tool registration
    3     gitTool
    4   ) where
    5 
    6 import Control.Exception
    7 import Data.Aeson
    8 import Data.Aeson.Types
    9 import Data.ByteString.Char8 qualified as BS8
   10 import Data.Text (Text)
   11 import Data.Text qualified as T
   12 import System.Exit
   13 
   14 import PureClaw.Handles.Shell
   15 import PureClaw.Providers.Class
   16 import PureClaw.Security.Command
   17 import PureClaw.Security.Policy
   18 import PureClaw.Tools.Registry
   19 
   20 -- | Create a git tool that executes git subcommands through the security policy.
   21 gitTool :: SecurityPolicy -> ShellHandle -> (ToolDefinition, ToolHandler)
   22 gitTool policy sh = (def, handler)
   23   where
   24     def = ToolDefinition
   25       { _td_name        = "git"
   26       , _td_description = "Execute git operations. Supports: status, diff, log, add, commit, branch, checkout, stash."
   27       , _td_inputSchema = object
   28           [ "type" .= ("object" :: Text)
   29           , "properties" .= object
   30               [ "subcommand" .= object
   31                   [ "type" .= ("string" :: Text)
   32                   , "description" .= ("The git subcommand and arguments, e.g. \"status\" or \"diff --cached\"" :: Text)
   33                   ]
   34               ]
   35           , "required" .= (["subcommand"] :: [Text])
   36           ]
   37       }
   38 
   39     handler = ToolHandler $ \input ->
   40       case parseEither parseInput input of
   41         Left err -> pure (T.pack err, True)
   42         Right subcmd -> do
   43           let args = T.words subcmd
   44           case authorize policy "git" args of
   45             Left (CommandNotAllowed _) -> pure ("git is not in the allowed commands list", True)
   46             Left CommandInAutonomyDeny -> pure ("All commands denied by security policy", True)
   47             Right authorized -> do
   48               result <- try @SomeException (_sh_execute sh authorized)
   49               case result of
   50                 Left e -> pure (T.pack (show e), True)
   51                 Right pr -> do
   52                   let out = T.pack (BS8.unpack (_pr_stdout pr))
   53                       err = T.pack (BS8.unpack (_pr_stderr pr))
   54                       exitInfo = case _pr_exitCode pr of
   55                         ExitSuccess -> ""
   56                         ExitFailure n -> "\nExit code: " <> T.pack (show n)
   57                       combined = T.strip (out <> err <> exitInfo)
   58                   pure (if T.null combined then "(no output)" else combined, False)
   59 
   60     parseInput :: Value -> Parser Text
   61     parseInput = withObject "GitInput" $ \o -> o .: "subcommand"