never executed always true always false
    1 module PureClaw.Tools.Memory
    2   ( -- * Tool registration
    3     memoryStoreTool
    4   , memoryRecallTool
    5   ) where
    6 
    7 import Control.Exception
    8 import Data.Aeson
    9 import Data.Aeson.Types
   10 import Data.Map.Strict qualified as Map
   11 import Data.Text (Text)
   12 import Data.Text qualified as T
   13 
   14 import PureClaw.Core.Types
   15 import PureClaw.Handles.Memory
   16 import PureClaw.Providers.Class
   17 import PureClaw.Tools.Registry
   18 
   19 -- | Create a memory store tool.
   20 memoryStoreTool :: MemoryHandle -> (ToolDefinition, ToolHandler)
   21 memoryStoreTool mh = (def, handler)
   22   where
   23     def = ToolDefinition
   24       { _td_name        = "memory_store"
   25       , _td_description = "Store a piece of information in long-term memory for later recall."
   26       , _td_inputSchema = object
   27           [ "type" .= ("object" :: Text)
   28           , "properties" .= object
   29               [ "content" .= object
   30                   [ "type" .= ("string" :: Text)
   31                   , "description" .= ("The content to remember" :: Text)
   32                   ]
   33               , "tags" .= object
   34                   [ "type" .= ("string" :: Text)
   35                   , "description" .= ("Comma-separated tags for categorization" :: Text)
   36                   ]
   37               ]
   38           , "required" .= (["content"] :: [Text])
   39           ]
   40       }
   41 
   42     handler = ToolHandler $ \input ->
   43       case parseEither parseInput input of
   44         Left err -> pure (T.pack err, True)
   45         Right (content, tags) -> do
   46           let source = MemorySource
   47                 { _ms_content  = content
   48                 , _ms_metadata = Map.fromList [("tags", tags)]
   49                 }
   50           result <- try @SomeException (_mh_save mh source)
   51           case result of
   52             Left e -> pure (T.pack (show e), True)
   53             Right Nothing -> pure ("Failed to store memory", True)
   54             Right (Just mid) -> pure ("Stored with id: " <> unMemoryId mid, False)
   55 
   56     parseInput :: Value -> Parser (Text, Text)
   57     parseInput = withObject "MemoryStoreInput" $ \o ->
   58       (,) <$> o .: "content" <*> o .:? "tags" .!= ""
   59 
   60 -- | Create a memory recall tool.
   61 memoryRecallTool :: MemoryHandle -> (ToolDefinition, ToolHandler)
   62 memoryRecallTool mh = (def, handler)
   63   where
   64     def = ToolDefinition
   65       { _td_name        = "memory_recall"
   66       , _td_description = "Search long-term memory for relevant information."
   67       , _td_inputSchema = object
   68           [ "type" .= ("object" :: Text)
   69           , "properties" .= object
   70               [ "query" .= object
   71                   [ "type" .= ("string" :: Text)
   72                   , "description" .= ("The search query" :: Text)
   73                   ]
   74               ]
   75           , "required" .= (["query"] :: [Text])
   76           ]
   77       }
   78 
   79     handler = ToolHandler $ \input ->
   80       case parseEither parseInput input of
   81         Left err -> pure (T.pack err, True)
   82         Right query -> do
   83           result <- try @SomeException (_mh_search mh query defaultSearchConfig)
   84           case result of
   85             Left e -> pure (T.pack (show e), True)
   86             Right [] -> pure ("No memories found for: " <> query, False)
   87             Right results ->
   88               let formatted = T.intercalate "\n---\n"
   89                     [ _sr_content r <> " (score: " <> T.pack (show (_sr_score r)) <> ")"
   90                     | r <- results
   91                     ]
   92               in pure (formatted, False)
   93 
   94     parseInput :: Value -> Parser Text
   95     parseInput = withObject "MemoryRecallInput" $ \o -> o .: "query"