diff options
Diffstat (limited to 'Omni/Agent/Log.hs')
| -rw-r--r-- | Omni/Agent/Log.hs | 102 |
1 files changed, 54 insertions, 48 deletions
diff --git a/Omni/Agent/Log.hs b/Omni/Agent/Log.hs index 99b40ae..59efb38 100644 --- a/Omni/Agent/Log.hs +++ b/Omni/Agent/Log.hs @@ -6,16 +6,16 @@ module Omni.Agent.Log where import Alpha +import Data.Aeson (Value (..), decode) +import qualified Data.Aeson.KeyMap as KM +import qualified Data.ByteString.Lazy as BL import Data.IORef (IORef, modifyIORef', newIORef, readIORef, writeIORef) +import qualified Data.Text.Encoding as TextEnc import qualified Data.Text.IO as TIO +import qualified Data.Vector as V import qualified System.Console.ANSI as ANSI import qualified System.IO as IO import System.IO.Unsafe (unsafePerformIO) -import Data.Aeson (Value(..), decode) -import qualified Data.Aeson.KeyMap as KM -import qualified Data.ByteString.Lazy as BL -import qualified Data.Text.Encoding as TextEnc -import qualified Data.Vector as V -- | Parsed log entry data LogEntry = LogEntry @@ -32,6 +32,7 @@ data LogEntry = LogEntry data Status = Status { statusWorker :: Text, statusTask :: Maybe Text, + statusThreadId :: Maybe Text, statusFiles :: Int, statusCredits :: Double, statusTime :: Text, -- formatted time string @@ -44,6 +45,7 @@ emptyStatus workerName = Status { statusWorker = workerName, statusTask = Nothing, + statusThreadId = Nothing, statusFiles = 0, statusCredits = 0.0, statusTime = "00:00", @@ -60,10 +62,9 @@ init :: Text -> IO () init workerName = do IO.hSetBuffering IO.stderr IO.LineBuffering writeIORef currentStatus (emptyStatus workerName) - -- Reserve 2 lines at bottom - IO.hPutStrLn IO.stderr "" - IO.hPutStrLn IO.stderr "" - ANSI.hCursorUp IO.stderr 2 + -- Reserve 5 lines at bottom + replicateM_ 5 (IO.hPutStrLn IO.stderr "") + ANSI.hCursorUp IO.stderr 5 -- | Update the status update :: (Status -> Status) -> IO () @@ -79,9 +80,7 @@ updateActivity msg = update (\s -> s {statusActivity = msg}) processLogLine :: Text -> IO () processLogLine line = do let entry = parseLine line - case entry >>= formatLogEntry of - Just msg -> updateActivity msg - Nothing -> pure () + Data.Foldable.for_ (entry +> formatLogEntry) updateActivity -- | Parse a JSON log line into a LogEntry parseLine :: Text -> Maybe LogEntry @@ -109,12 +108,12 @@ parseLine line = do getBatches o = case KM.lookup "batches" o of Just (Array b) -> - Just <| - mapMaybe + Just + <| mapMaybe ( \case Array b0 -> - Just <| - mapMaybe + Just + <| mapMaybe ( \case String s -> Just s _ -> Nothing @@ -135,37 +134,38 @@ formatLogEntry LogEntry {..} = ((t : _) : _) -> t _ -> "unknown" Just ("THOUGHT: Planning tool execution (" <> firstTool <> ")") - Just "Tool Bash permitted - action: allow" -> Just "TOOL: Bash command executed" - - Just "Processing tool completion for ledger" | isJust leToolName -> - Just ("TOOL: " <> fromMaybe "unknown" leToolName <> " completed") - + Just "Processing tool completion for ledger" + | isJust leToolName -> + Just ("TOOL: " <> fromMaybe "unknown" leToolName <> " completed") Just "ide-fs" | leMethod == Just "readFile" -> case lePath of Just p -> Just ("READ: " <> p) _ -> Nothing - Just "System prompt build complete (no changes)" -> Just "THINKING..." - Just "System prompt build complete (first build)" -> Just "STARTING new task context" - - Just msg | leLevel == Just "error" -> - Just ("ERROR: " <> msg) - + Just msg + | leLevel == Just "error" -> + Just ("ERROR: " <> msg) _ -> Nothing -- | Log a scrolling message (appears above status bars) log :: Text -> IO () log msg = do - -- Clear status bars + -- Clear status bars (5 lines) + ANSI.hClearLine IO.stderr + ANSI.hCursorDown IO.stderr 1 ANSI.hClearLine IO.stderr ANSI.hCursorDown IO.stderr 1 ANSI.hClearLine IO.stderr - ANSI.hCursorUp IO.stderr 1 + ANSI.hCursorDown IO.stderr 1 + ANSI.hClearLine IO.stderr + ANSI.hCursorDown IO.stderr 1 + ANSI.hClearLine IO.stderr + ANSI.hCursorUp IO.stderr 4 -- Print message (scrolls screen) TIO.hPutStrLn IO.stderr msg @@ -174,37 +174,43 @@ log msg = do -- (Since we scrolled, we are now on the line above where the first status line should be) render --- | Render the two status lines +-- | Render the 5 status lines (Vertical Layout) render :: IO () render = do Status {..} <- readIORef currentStatus - -- Line 1: Meta - -- [Worker: name] Task: t-123 | Files: 3 | Credits: $0.45 | Time: 05:23 let taskStr = maybe "None" identity statusTask - meta = - "[Worker: " - <> statusWorker - <> "] Task: " - <> taskStr - <> " | Files: " - <> tshow statusFiles - <> " | Credits: $" - <> tshow statusCredits - <> " | Time: " - <> statusTime + threadStr = maybe "None" identity statusThreadId + + -- Line 1: Worker + Time + ANSI.hSetCursorColumn IO.stderr 0 + ANSI.hClearLine IO.stderr + TIO.hPutStr IO.stderr <| "Worker: " <> statusWorker <> " | Time: " <> statusTime + + -- Line 2: Task + ANSI.hCursorDown IO.stderr 1 + ANSI.hSetCursorColumn IO.stderr 0 + ANSI.hClearLine IO.stderr + TIO.hPutStr IO.stderr <| "Task: " <> taskStr + + -- Line 3: Thread + ANSI.hCursorDown IO.stderr 1 + ANSI.hSetCursorColumn IO.stderr 0 + ANSI.hClearLine IO.stderr + TIO.hPutStr IO.stderr <| "Thread: " <> threadStr + -- Line 4: Credits + ANSI.hCursorDown IO.stderr 1 ANSI.hSetCursorColumn IO.stderr 0 ANSI.hClearLine IO.stderr - TIO.hPutStr IO.stderr meta + TIO.hPutStr IO.stderr <| "Credits: $" <> tshow statusCredits - -- Line 2: Activity - -- [14:05:22] > Thinking... + -- Line 5: Activity ANSI.hCursorDown IO.stderr 1 ANSI.hSetCursorColumn IO.stderr 0 ANSI.hClearLine IO.stderr TIO.hPutStr IO.stderr ("> " <> statusActivity) - -- Return cursor to line 1 - ANSI.hCursorUp IO.stderr 1 + -- Return cursor to Line 1 + ANSI.hCursorUp IO.stderr 4 IO.hFlush IO.stderr |
