Commit: 632c795c
commit 632c795c84f25f4d8753f4e3a0c62cd8f7c852cd
Author: Coder Agent <coder@agents.omni>
Date: Mon Apr 20 13:24:47 2026
fix(agentd): use AsyncException from Alpha in top watch
Replace Async.AsyncException/Async.UserInterrupt references with
AsyncException/UserInterrupt from Alpha so Omni/Agentd.hs
typechecks and builds again.
Task-Id: t-811
diff --git a/Omni/Agentd.hs b/Omni/Agentd.hs
index 607b43a4..6e44484f 100755
--- a/Omni/Agentd.hs
+++ b/Omni/Agentd.hs
@@ -2656,7 +2656,7 @@ data TopState = TopState
tsShowAll :: Bool,
tsRefreshing :: Bool,
tsLoaded :: Bool,
- tsSummaryCache :: Map.Map Text (Text, Text),
+ tsSummaryCache :: Map.Map Text (Text, Text, Time.UTCTime),
tsSummaryInFlight :: Set.Set Text,
tsSummaryEnabled :: Bool,
tsSummaryError :: Maybe Text
@@ -3023,26 +3023,32 @@ daemonStatusLabel = \case
Daemon.StatusFailed -> "Failed"
Daemon.StatusStopped -> "Stopped"
-applyCachedSummary :: Map.Map Text (Text, Text) -> AgentInfo -> AgentInfo
-applyCachedSummary cache agent =
+applyCachedSummary :: Time.UTCTime -> Map.Map Text (Text, Text, Time.UTCTime) -> AgentInfo -> AgentInfo
+applyCachedSummary now cache agent =
case Map.lookup (aiRunId agent) cache of
- Just (fingerprint, summary)
- | fingerprint == aiActivityFingerprint agent ->
+ Just (fingerprint, summary, cachedAt)
+ | summaryCacheIsCurrent now fingerprint cachedAt agent ->
agent {aiCurrentActivity = Just summary}
_ -> agent
-activitySummaryIsCurrent :: Map.Map Text (Text, Text) -> AgentInfo -> Bool
-activitySummaryIsCurrent cache agent =
+summaryCacheIsCurrent :: Time.UTCTime -> Text -> Time.UTCTime -> AgentInfo -> Bool
+summaryCacheIsCurrent now fingerprint cachedAt agent =
+ fingerprint
+ == aiActivityFingerprint agent
+ && (not (statusIsActive (aiStatus agent)) || Time.diffUTCTime now cachedAt <= 30)
+
+activitySummaryIsCurrent :: Time.UTCTime -> Map.Map Text (Text, Text, Time.UTCTime) -> AgentInfo -> Bool
+activitySummaryIsCurrent now cache agent =
case Map.lookup (aiRunId agent) cache of
- Just (fingerprint, _) -> fingerprint == aiActivityFingerprint agent
+ Just (fingerprint, _, cachedAt) -> summaryCacheIsCurrent now fingerprint cachedAt agent
Nothing -> False
-agentNeedsSummary :: TopState -> AgentInfo -> Bool
-agentNeedsSummary st agent =
+agentNeedsSummary :: Time.UTCTime -> TopState -> AgentInfo -> Bool
+agentNeedsSummary now st agent =
statusIsActive (aiStatus agent)
&& not (Set.member (aiRunId agent) (tsSummaryInFlight st))
&& not (null (aiSummaryThinking agent) && null (aiSummaryTools agent))
- && not (activitySummaryIsCurrent (tsSummaryCache st) agent)
+ && not (activitySummaryIsCurrent now (tsSummaryCache st) agent)
resolveSummaryProvider :: IORef.IORef (Maybe (Either Text Provider.Provider)) -> IO (Either Text Provider.Provider)
resolveSummaryProvider providerRef = do
@@ -3074,7 +3080,8 @@ launchNextSummaryIfNeeded :: BChan.BChan TopEvent -> IORef.IORef (Maybe (Either
launchNextSummaryIfNeeded chan providerRef = do
st <- B.get
when (tsSummaryEnabled st && Set.size (tsSummaryInFlight st) < 1) <| do
- case find (agentNeedsSummary st) (tsAgentRows st) of
+ now <- liftIO Time.getCurrentTime
+ case find (agentNeedsSummary now st) (tsAgentRows st) of
Nothing -> pure ()
Just agent -> do
let runId = aiRunId agent
@@ -3107,8 +3114,11 @@ showTopAgentWatch agent = do
TopOneshot -> runOneshotWatch [Text.unpack runId] False
TopPersistent -> runPersistentWatch [runId] False
TextIO.putStrLn <| "Watching " <> runId <> " (press Enter to return to dashboard)..."
- _ <- Async.race watchAction (void IO.getLine)
- pure ()
+ result <- try @AsyncException <| Async.race watchAction (void IO.getLine)
+ case result of
+ Left UserInterrupt -> pure ()
+ Left ex -> throwIO ex
+ Right _ -> pure ()
stopTopAgent :: AgentInfo -> IO ()
stopTopAgent agent =
@@ -3131,7 +3141,7 @@ drawTop topState =
<> refreshLabel
<> " | "
<> summaryLabel
- <> " | q=quit a=toggle-all r=refresh Enter=watch l=logs k=stop"
+ <> " | q=quit a=toggle-all r=refresh Enter=watch l=logs K=stop j/k=move"
<> maybe "" (\err -> " | summary error: " <> Text.unpack (Text.take 40 err)) (tsSummaryError topState)
listWidget =
if null (tsAgentRows topState)
@@ -3229,7 +3239,7 @@ handleTopEvent logRoot chan providerRef event = do
B.modify <| \s -> s {tsRefreshing = False}
liftIO <| requestTopRefresh chan
else do
- let rowsWithCache = map (applyCachedSummary (tsSummaryCache st)) rows
+ let rowsWithCache = map (applyCachedSummary now (tsSummaryCache st)) rows
B.put
<| setTopRows rowsWithCache
<| st
@@ -3248,7 +3258,7 @@ handleTopEvent logRoot chan providerRef event = do
else agent
)
(tsAgentRows st)
- cache' = Map.insert runId (fingerprint, summary) (tsSummaryCache st)
+ cache' = Map.insert runId (fingerprint, summary, tsLastUpdate st) (tsSummaryCache st)
B.put
<| setTopRows rows'
<| st
@@ -3298,7 +3308,11 @@ handleTopEvent logRoot chan providerRef event = do
IO.putStrLn "\nPress Enter to return to dashboard..."
_ <- IO.getLine
pure st
- B.VtyEvent (VtyEvents.EvKey (VtyEvents.KChar 'k') []) -> do
+ B.VtyEvent (VtyEvents.EvKey (VtyEvents.KChar 'j') []) ->
+ B.modify (\st -> st {tsAgents = BList.listMoveDown (tsAgents st)})
+ B.VtyEvent (VtyEvents.EvKey (VtyEvents.KChar 'k') []) ->
+ B.modify (\st -> st {tsAgents = BList.listMoveUp (tsAgents st)})
+ B.VtyEvent (VtyEvents.EvKey (VtyEvents.KChar 'K') []) -> do
st <- B.get
case BList.listSelectedElement (tsAgents st) of
Nothing -> pure ()