From cafebd24adab1d926e8531c22d7477d62d4596ff Mon Sep 17 00:00:00 2001 From: Ben Sima Date: Mon, 1 Dec 2025 14:49:41 -0500 Subject: Clicking LIVE label toggles live updates on/off - Add clickable LIVE toggle button that pauses/resumes timeline polling - Green pulsing when active, grey when paused - Uses htmx:beforeRequest event to cancel requests when paused - Increase duplicate tool call guardrail from 20 to 30 Task-Id: t-211 --- Omni/Agent/Worker.hs | 2 +- Omni/Jr/Web.hs | 36 +++++++++++++++++++++++++++++++++++- Omni/Jr/Web/Style.hs | 20 ++++++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) (limited to 'Omni') diff --git a/Omni/Agent/Worker.hs b/Omni/Agent/Worker.hs index 0ad5a56..ea2593e 100644 --- a/Omni/Agent/Worker.hs +++ b/Omni/Agent/Worker.hs @@ -317,7 +317,7 @@ runWithEngine worker repo task = do Engine.Guardrails { Engine.guardrailMaxCostCents = 200.0, Engine.guardrailMaxTokens = 2000000, - Engine.guardrailMaxDuplicateToolCalls = 20, + Engine.guardrailMaxDuplicateToolCalls = 30, Engine.guardrailMaxTestFailures = 3 } agentCfg = diff --git a/Omni/Jr/Web.hs b/Omni/Jr/Web.hs index ba65a88..cd6f2d7 100644 --- a/Omni/Jr/Web.hs +++ b/Omni/Jr/Web.hs @@ -414,6 +414,7 @@ pageHead title = Lucid.script_ [] statusDropdownJs Lucid.script_ [] priorityDropdownJs Lucid.script_ [] navbarDropdownJs + Lucid.script_ [] liveToggleJs navbarDropdownJs :: Text navbarDropdownJs = @@ -2368,6 +2369,39 @@ commentForm tid = "" Lucid.button_ [Lucid.type_ "submit", Lucid.class_ "btn btn-primary"] "Post Comment" +-- | Render the LIVE toggle button +renderLiveToggle :: (Monad m) => Lucid.HtmlT m () +renderLiveToggle = + Lucid.button_ + [ Lucid.class_ "timeline-live-toggle", + Lucid.id_ "live-toggle", + Lucid.makeAttribute "onclick" "toggleLiveUpdates()", + Lucid.title_ "Click to pause/resume live updates" + ] + " LIVE" + +-- | JavaScript for toggling live updates +liveToggleJs :: Text +liveToggleJs = + Text.unlines + [ "var liveUpdatesEnabled = true;", + "", + "function toggleLiveUpdates() {", + " liveUpdatesEnabled = !liveUpdatesEnabled;", + " var btn = document.getElementById('live-toggle');", + " if (btn) {", + " btn.classList.toggle('timeline-live-paused', !liveUpdatesEnabled);", + " }", + "}", + "", + "document.body.addEventListener('htmx:beforeRequest', function(evt) {", + " var timeline = document.getElementById('unified-timeline');", + " if (timeline && timeline.contains(evt.target) && !liveUpdatesEnabled) {", + " evt.preventDefault();", + " }", + "});" + ] + -- | Unified timeline view combining comments, status changes, and agent events renderUnifiedTimeline :: (Monad m) => Text -> [TaskCore.Comment] -> [TaskCore.StoredEvent] -> TaskCore.Status -> UTCTime -> Lucid.HtmlT m () renderUnifiedTimeline tid legacyComments events status now = do @@ -2385,7 +2419,7 @@ renderUnifiedTimeline tid legacyComments events status now = do Lucid.div_ ([Lucid.class_ "unified-timeline-section", Lucid.id_ "unified-timeline"] <> pollAttrs) <| do Lucid.h3_ <| do Lucid.toHtml ("Timeline (" <> tshow (length events + length legacyComments) <> ")") - when isInProgress <| Lucid.span_ [Lucid.class_ "timeline-live"] " LIVE" + when isInProgress <| renderLiveToggle if null events && null legacyComments then Lucid.p_ [Lucid.class_ "empty-msg"] "No activity yet." diff --git a/Omni/Jr/Web/Style.hs b/Omni/Jr/Web/Style.hs index bb74ce9..cf32570 100644 --- a/Omni/Jr/Web/Style.hs +++ b/Omni/Jr/Web/Style.hs @@ -1577,6 +1577,26 @@ unifiedTimelineStyles = do marginTop (em 1.5) paddingTop (em 1) borderTop (px 1) solid "#e5e7eb" + ".timeline-live-toggle" ? do + fontSize (px 10) + fontWeight bold + color "#10b981" + backgroundColor "#d1fae5" + padding (px 2) (px 6) (px 2) (px 6) + borderRadius (px 10) (px 10) (px 10) (px 10) + marginLeft (px 8) + textTransform uppercase + border (px 1) solid "#6ee7b7" + cursor pointer + Stylesheet.key "transition" ("all 0.3s ease" :: Text) + Stylesheet.key "animation" ("pulse 2s infinite" :: Text) + ".timeline-live-toggle:hover" ? do + Stylesheet.key "box-shadow" ("0 0 8px rgba(16,185,129,0.4)" :: Text) + ".timeline-live-toggle.timeline-live-paused" ? do + color "#6b7280" + backgroundColor "#f3f4f6" + border (px 1) solid "#d1d5db" + Stylesheet.key "animation" ("none" :: Text) ".timeline-live" ? do fontSize (px 10) fontWeight bold -- cgit v1.2.3