never executed always true always false
    1 module PureClaw.Handles.Channel
    2   ( -- * Message types
    3     IncomingMessage (..)
    4   , OutgoingMessage (..)
    5     -- * Streaming
    6   , StreamChunk (..)
    7     -- * Handle type
    8   , ChannelHandle (..)
    9     -- * Implementations
   10   , mkNoOpChannelHandle
   11   ) where
   12 
   13 import Data.Text (Text)
   14 
   15 import PureClaw.Core.Errors
   16 import PureClaw.Core.Types
   17 
   18 -- | A message received from a channel user.
   19 data IncomingMessage = IncomingMessage
   20   { _im_userId  :: UserId
   21   , _im_content :: Text
   22   }
   23   deriving stock (Show, Eq)
   24 
   25 -- | A message to send to a channel user.
   26 newtype OutgoingMessage = OutgoingMessage
   27   { _om_content :: Text
   28   }
   29   deriving stock (Show, Eq)
   30 
   31 -- | A chunk of streamed text from the provider.
   32 data StreamChunk
   33   = ChunkText Text    -- ^ Partial text content
   34   | ChunkDone         -- ^ Stream finished
   35   deriving stock (Show, Eq)
   36 
   37 -- | Channel communication capability interface. Concrete implementations
   38 -- (CLI, Telegram, Signal) live in @PureClaw.Channels.*@ modules.
   39 --
   40 -- 'sendError' only accepts 'PublicError' — internal errors with stack
   41 -- traces or model names cannot be sent to channel users. This is enforced
   42 -- at the type level.
   43 data ChannelHandle = ChannelHandle
   44   { _ch_receive      :: IO IncomingMessage
   45   , _ch_send         :: OutgoingMessage -> IO ()
   46   , _ch_sendError    :: PublicError -> IO ()
   47   , _ch_sendChunk    :: StreamChunk -> IO ()
   48   , _ch_streaming    :: Bool
   49     -- ^ Whether this channel supports streaming output. When 'True',
   50     -- the agent loop sends text via '_ch_sendChunk' during generation
   51     -- and skips the full '_ch_send'. When 'False', only '_ch_send'
   52     -- is used for the final complete response.
   53   , _ch_readSecret   :: IO Text    -- ^ Read a line without echo (CLI only)
   54   , _ch_prompt       :: Text -> IO Text
   55     -- ^ Display a prompt and read input on the same line (no trailing
   56     -- newline after the prompt text). For non-interactive channels this
   57     -- falls back to send-then-receive.
   58   , _ch_promptSecret :: Text -> IO Text
   59     -- ^ Like '_ch_prompt' but with echo disabled (for passwords / API keys).
   60     -- For non-interactive channels this falls back to '_ch_readSecret'.
   61   }
   62 
   63 -- | No-op channel handle. Receive returns an empty message, send and
   64 -- sendError are silent. readSecret returns empty text.
   65 mkNoOpChannelHandle :: ChannelHandle
   66 mkNoOpChannelHandle = ChannelHandle
   67   { _ch_receive      = pure (IncomingMessage (UserId "") "")
   68   , _ch_send         = \_ -> pure ()
   69   , _ch_sendError    = \_ -> pure ()
   70   , _ch_sendChunk    = \_ -> pure ()
   71   , _ch_streaming    = False
   72   , _ch_readSecret   = pure ""
   73   , _ch_prompt       = \_ -> pure ""
   74   , _ch_promptSecret = \_ -> pure ""
   75   }