{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE NoImplicitPrelude #-} -- : out agent-log-test module Omni.Agent.LogTest where import Alpha import qualified Data.Set as Set import Omni.Agent.Log import qualified Omni.Test as Test main :: IO () main = Test.run tests tests :: Test.Tree tests = Test.group "Omni.Agent.Log" [ Test.unit "Parse LogEntry" testParse, Test.unit "Format LogEntry" testFormat, Test.unit "Update Status" testUpdateStatus, Test.unit "Render Status" testRenderStatus ] testParse :: IO () testParse = do let json = "{\"message\": \"executing 1 tools in 1 batch(es)\", \"batches\": [[\"grep\"]]}" let expected = LogEntry { leMessage = "executing 1 tools in 1 batch(es)", leLevel = Nothing, leToolName = Nothing, leBatches = Just [["grep"]], leMethod = Nothing, lePath = Nothing, leTimestamp = Nothing } parseLine json @?= Just expected testFormat :: IO () testFormat = do let entry = LogEntry { leMessage = "executing 1 tools in 1 batch(es)", leLevel = Nothing, leToolName = Nothing, leBatches = Just [["grep"]], leMethod = Nothing, lePath = Nothing, leTimestamp = Nothing } format entry @?= Just "🤖 THOUGHT: Planning tool execution (grep)" let entry2 = LogEntry { leMessage = "some random log", leLevel = Nothing, leToolName = Nothing, leBatches = Nothing, leMethod = Nothing, lePath = Nothing, leTimestamp = Nothing } format entry2 @?= Nothing let entry3 = LogEntry { leMessage = "some error", leLevel = Just "error", leToolName = Nothing, leBatches = Nothing, leMethod = Nothing, lePath = Nothing, leTimestamp = Nothing } format entry3 @?= Just "❌ ERROR: some error" testUpdateStatus :: IO () testUpdateStatus = do let s0 = initialStatus "worker-1" let e1 = LogEntry { leMessage = "executing 1 tools in 1 batch(es)", leLevel = Nothing, leToolName = Nothing, leBatches = Just [["grep"]], leMethod = Nothing, lePath = Nothing, leTimestamp = Just "12:00:00" } let s1 = updateStatus e1 s0 sLastActivity s1 @?= "🤖 THOUGHT: Planning tool execution (grep)" sStartTime s1 @?= Just "12:00:00" let e2 = LogEntry { leMessage = "ide-fs", leLevel = Nothing, leToolName = Nothing, leBatches = Nothing, leMethod = Just "readFile", lePath = Just "/path/to/file", leTimestamp = Just "12:00:01" } let s2 = updateStatus e2 s1 sLastActivity s2 @?= "📂 READ: /path/to/file" Set.member "/path/to/file" (sFiles s2) @?= True sStartTime s2 @?= Just "12:00:00" -- Should preserve start time testRenderStatus :: IO () testRenderStatus = do let s = Status { sWorkerName = "worker-1", sTaskId = Just "t-123", sFiles = Set.fromList ["file1", "file2"], sStartTime = Just "12:00", sLastActivity = "Running..." } let output = renderStatus s output @?= "[Worker: worker-1] Task: t-123 | Files: 2\nRunning..." (@?=) :: (Eq a, Show a) => a -> a -> IO () (@?=) = (Test.@?=)