kioku-cli-0.1.0.0: src/Kioku/Cli/Commands/Demo.hs
module Kioku.Cli.Commands.Demo
( DemoOptions (..),
demoOptionsParser,
demoScope,
runDemo,
)
where
import Data.Set qualified as Set
import Data.Text qualified as Text
import Data.Time (getCurrentTime)
import Kioku.Api.Scope (MemoryScope (..), Namespace (..), ScopeKind (..))
import Kioku.Api.Types (Confidence (..), MemoryRecord (..), MemoryType (..))
import Kioku.App (runAppIO, withNoopAppEnv)
import Kioku.Cli.Options (redactConnectionString, yesWriteEventsFlag)
import Kioku.Id (genMemoryId, idText)
import Kioku.Memory qualified as Memory
import Kioku.Memory.Domain (RecordMemoryData (..))
import Kioku.Recall qualified as Recall
import Kiroku.Store.Connection (defaultConnectionSettings)
import Options.Applicative
import System.Environment (lookupEnv)
data DemoOptions = DemoOptions
deriving stock (Eq, Show)
demoOptionsParser :: Parser DemoOptions
demoOptionsParser = DemoOptions <$ yesWriteEventsFlag
-- | The demo writes into a namespace nothing else reads.
--
-- It used to write into @rei:intention:intention_demo@ — the same namespace real Rei data
-- lives in — and those events are permanent, because kioku has no delete. They also fed the
-- distillation timers. A dedicated @kioku_demo@ namespace makes demo residue unmistakable and
-- keeps distillation of demo data confined to a namespace nothing else reads.
demoScope :: MemoryScope
demoScope = ScopeEntity (Namespace "kioku_demo") (ScopeKind "demo") "demo"
runDemo :: DemoOptions -> IO ()
runDemo DemoOptions = do
connStr <- requireEnv "PG_CONNECTION_STRING"
putStrLn "kioku demo appends permanent memory events (kioku has no delete)."
putStrLn ("Target: " <> Text.unpack (redactConnectionString (Text.pack connStr)))
putStrLn "Scope: kioku_demo/demo/demo"
withNoopAppEnv (defaultConnectionSettings (Text.pack connStr)) \env -> do
mid <- genMemoryId
now <- getCurrentTime
let scope = demoScope
payload =
RecordMemoryData
{ memoryId = mid,
agentId = "demo-agent",
sessionId = Nothing,
scope = scope,
memoryType = MemoryPreference,
content = "prefers concise answers",
priority = 100,
confidence = HighConfidence,
tags = Set.fromList ["style"],
supersedes = Nothing,
recordedAt = now
}
result <- runAppIO env do
writeResult <- Memory.record payload
recallResult <- Recall.getActiveByScope scope
pure (writeResult, recallResult)
case result of
Left storeErr -> ioError (userError ("kioku demo store error: " <> show storeErr))
Right (Left writeErr, _) -> ioError (userError ("kioku demo write error: " <> show writeErr))
Right (Right writtenId, Left recallErr) ->
ioError (userError ("kioku demo recall error after writing " <> show writtenId <> ": " <> show recallErr))
Right (Right writtenId, Right records) -> do
putStrLn ("Recorded memory " <> Text.unpack (idText writtenId) <> " in scope kioku_demo/demo/demo")
mapM_ printRecord records
requireEnv :: String -> IO String
requireEnv name = do
found <- lookupEnv name
case found of
Just value -> pure value
Nothing -> ioError (userError (name <> " is not set"))
printRecord :: MemoryRecord -> IO ()
printRecord record =
putStrLn $
"- "
<> Text.unpack record.memoryId
<> " ["
<> Text.unpack record.memoryType
<> "/"
<> Text.unpack record.confidence
<> "] "
<> Text.unpack record.content