never executed always true always false
    1 module PureClaw.Channels.CLI
    2   ( -- * CLI channel
    3     mkCLIChannelHandle
    4   ) where
    5 
    6 import Data.Maybe qualified
    7 import Data.Text qualified as T
    8 import Data.Text.IO qualified as TIO
    9 import System.Console.Haskeline qualified as HL
   10 import System.Directory (createDirectoryIfMissing)
   11 import System.IO (hFlush, stderr, stdout)
   12 
   13 import PureClaw.CLI.Config (getPureclawDir)
   14 import PureClaw.Core.Types
   15 import PureClaw.Handles.Channel
   16 
   17 -- | Create a channel handle that uses haskeline for line editing.
   18 -- Provides readline-style input: backspace, arrow keys, up/down history,
   19 -- Ctrl-A/E, etc. History is persisted to @~\/.pureclaw\/history@.
   20 -- Accepts an optional completion function for tab completion of slash commands.
   21 mkCLIChannelHandle :: Maybe (HL.CompletionFunc IO) -> IO ChannelHandle
   22 mkCLIChannelHandle mCompleter = do
   23   histPath <- haskelineHistoryPath
   24   let settings = (HL.defaultSettings :: HL.Settings IO)
   25         { HL.historyFile = Just histPath
   26         , HL.complete = Data.Maybe.fromMaybe HL.completeFilename mCompleter
   27         }
   28   pure ChannelHandle
   29     { _ch_receive = do
   30         mLine <- HL.runInputT settings (HL.getInputLine "> ")
   31         case mLine of
   32           Nothing   -> ioError (userError "EOF")  -- Ctrl-D: agent loop catches this
   33           Just line -> pure IncomingMessage
   34             { _im_userId  = UserId "cli-user"
   35             , _im_content = T.pack line
   36             }
   37     , _ch_send = \msg -> do
   38         TIO.putStrLn ""
   39         TIO.putStrLn (_om_content msg)
   40         TIO.putStrLn ""
   41     , _ch_sendError = \err ->
   42         TIO.hPutStrLn stderr $ "Error: " <> T.pack (show err)
   43     , _ch_sendChunk = \case
   44         ChunkText t -> do
   45           TIO.putStr t
   46           hFlush stdout
   47         ChunkDone -> TIO.putStrLn ""
   48     , _ch_streaming = True
   49     , _ch_readSecret = do
   50         mLine <- HL.runInputT settings (HL.getPassword Nothing "")
   51         pure (maybe "" T.pack mLine)
   52     , _ch_prompt = \promptText -> do
   53         mLine <- HL.runInputT settings (HL.getInputLine (T.unpack promptText))
   54         pure (maybe "" T.pack mLine)
   55     , _ch_promptSecret = \promptText -> do
   56         mLine <- HL.runInputT settings (HL.getPassword Nothing (T.unpack promptText))
   57         pure (maybe "" T.pack mLine)
   58     }
   59 
   60 -- | Path to the haskeline history file: @~\/.pureclaw\/history@.
   61 -- Creates the directory if it does not exist.
   62 haskelineHistoryPath :: IO FilePath
   63 haskelineHistoryPath = do
   64   dir <- getPureclawDir
   65   createDirectoryIfMissing True dir
   66   pure (dir <> "/history")